牛客周赛 Round 142 题解

比赛链接

A 小苯的ovo3.0

知识点:语法

思路:分别判断三个字符是不是即可

Code
点击查看代码
void solve()
{
    cin>>s;
    if(s[0]=='o'||s[0]=='O')
    {
        if(s[2]=='o'||s[2]=='O')
        {
            if(s[1]=='v'||s[1]=='V')
            {
                cout<<"YES"<<endl;
                return;
            }
        }
    }
    cout<<"NO"<<endl;
    
}

B 小苯的双端队列

知识点:语法

思路:设置两个指针,初始一个在最左边,一个在最右边,遍历序列,哪一个符合就往中间缩,一旦出现两个都不符合的情况说明序列不合法

Code
点击查看代码
void solve()
{
    cin>>n;
    vi a(n+1);
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    l=1,r=n;
    for(int i=1;i<=n;i++)
    {
        if(a[i]==l)
        {
            l++;
            continue;
        }
        if(a[i]==r)
        {
            r--;
            continue;
        }
        cout<<"NO"<<endl;
        return;
    }
    cout<<"YES"<<endl;
}

C 小苯的整除序列

知识点:贪心

思路:很容易注意到对于同一个数,在序列的前面整除它,比在序列的后面整除它更优,更容易让结果序列更长,所以我们贪心,从左侧遍历序列,一旦可以整除就接着试下一个数,能够整除的次数即为序列长度

Code
点击查看代码
void solve()
{
    cin>>n;
    vi a(n+1);
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    int now=1;
    for(int i=1;i<=n;i++)
    {
        if(a[i]%now==0)
        {
            now++;
        }
    }
    cout<<now-1<<endl;
}

D 小苯的幼儿园

知识点:思维

思路:如果糖果数量总和不能整除小朋友的数量,一定不合法。因为每个小朋友只能操作一次,所以如果有一个小朋友糖的数量比平均值大 \(2\) 或以上,一定不合法,如果有一个小朋友糖的数量加上 \(1\) 依旧不是平均值,一定不合法,如果小朋友糖的数量比平均值大 \(1\),传给下一个小朋友,这样判断下来如果全符合,那么就可以达成均分

Code
点击查看代码
void solve()
{
    cin>>n;
    vi a(n+8);
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
        sum+=a[i];
    }
    if(sum%n!=0)
    {
        cout<<"NO"<<endl;
        return;
    }
    int v=sum/n;
    a[n+1]=a[1];
    for(int i=1;i<=n+1;i++)
    {
        if(a[i]-v>=2||a[i]+1<v)
        {
            cout<<"NO"<<endl;
            return;
        }
        if(a[i]==v+1)
        {
            a[i]-=1;
            a[i+1]++;
        }
    }
    cout<<"YES"<<endl;
}

E 小苯的区间操作

知识点:思维

思路:如果序列中有峰值,即 \(a_i>a_{i-1}\) 并且 \(a_i>a_{i+1}\),想要将峰值减成 \(0\),因为 \(a_{i-1}\)\(a_{i+1}\) 的约束,所有想要包含 \(a_i\) 的操作区间一定也会包括 \(a_{i+1}\)\(a_{i-1}\) ,如果想要将 \(a_i\) 作为端点,因为他是峰值,它旁边的数一定会先减成 \(0\),所以 \(a_i\) 永远不可能减成 \(0\),所以显然如果存在峰值,一定不合法,如果没有峰值呢?我们可以先找到一个最大值序列,将这个序列减成和外部数相同后合并成更大的序列,以此类推一定可以减成 \(0\),

点击查看代码
void solve()
{
    cin>>n;
    vi a(n+4);
    for(int i=1;i<=n;i++)
    {
        cin>>a[i];
    }
    for(int i = 1; i <= n;i++) 
    {
        if(a[i]>a[i - 1]&&a[i]>a[i + 1]) 
        {
            cout<<"No"<<endl;
            return;
        }
    }
    cout<<"Yes"<<endl;
}

F 小苯的DFS

知识点:dfs,贪心

思路:由题意得,共有两个限制,对于某一棵子树来说,根节点权值必须必须是子树中的最小值,对于某一个父亲节点的两个儿子来说,先遍历子树中的最大值必须小于等于后遍历子树中的最小值。我们求出每个子树中的最大和最小权值,对每个子树儿子所构成的所有权值区间进行排序,凡是有不满足两个限制的,概率一律为 \(0\),对于满足限制的为合法情况,对于排好序的权值区间数组来讲,可能存在某些权值区间是一样的,意味着先遍历哪一个都可以,会产生多种情况,情况数量为相同权值区间数量阶乘的乘积(设相同权值区间的数量为 \(c_i\),设总遍历方案数为 \(k!\) ,结果为 \(\frac{c_{1}!\times c_{2}!\times \ldots}{k!}\)

Code
点击查看代码
int fac[M];
int inv[M];
void init()
{
    fac[0] = 1;
    for (int i = 1; i < M; i++)
    {
        fac[i] = fac[i - 1] * i % mod;
    }
    inv[M - 1] = ksm(fac[M - 1], mod - 2, mod);
    for (int i = M - 2; i >= 0; i--)
    {
        inv[i] = inv[i + 1] * (i + 1) % mod;
    }
}
vi adj[M];
int ok;
int ans;
vi mi, mx, a;
void dfs(int u, int fa)
{
    mi[u] = a[u];
    mx[u] = a[u];
    vector<pii> p;
    for (int v : adj[u])
    {
        if (v == fa)
            continue;
        dfs(v, u);
        if (!ok)
            return;
        mi[u] = min(mi[u], mi[v]);
        mx[u] = max(mx[u], mx[v]);
        p.pb({mi[v], mx[v]});
    }
    if (a[u] != mi[u])
    {
        ok = 0;
        return;
    }
    if (!p.empty())
    {
        sort(all(p));
        for (int i = 0; i < (int)p.size() - 1; i++)
        {
            if (p[i].second > p[i + 1].first)
            {
                ok = 0;
                return;
            }
        }

        int res = 1;
        int cnt = 1;
        for (int i = 1; i < (int)p.size(); i++)
        {
            if (p[i] == p[i - 1])
            {
                cnt++;
            }
            else
            {
                res = res * fac[cnt] % mod;
                cnt = 1;
            }
        }
        res = res * fac[cnt] % mod;
        int c = res * inv[p.size()] % mod;
        ans = ans * c % mod;
    }
}
void solve()
{
    cin >> n;
    a.resize(n + 1);
    mx.resize(n + 1);
    mi.resize(n + 1);
    for (int i = 1; i <= n; i++)
    {
        adj[i].clear();
    }
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
    }
    for (int i = 1; i < n; i++)
    {
        int u, v;
        cin >> u >> v;
        adj[u].pb(v);
        adj[v].pb(u);
    }
    ok = 1;
    ans = 1;
    dfs(1, 0);
    if (!ok)
    {
        cout << 0 << endl;
    }
    else
    {
        cout << ans << endl;
    }
}
posted @ 2026-05-03 21:00  Lambda_L  阅读(50)  评论(0)    收藏  举报