牛客练习赛6 B,D 题解

比赛传送门
B:
首先不要把题想太复杂了, 只需要维护好几个值就OK了, 首先是5个数组
fa[x] 表示 x 的父亲是谁
son[x] 表示x有说多少个儿子
op[x] 表示x被操作的次数
a[x] 表示x的儿子对x的影响数
b[x] 表示x的孙子对x的影响数

有了这些的基础, 那么对于每次我们操作的点u的点权和res, 首先是他父亲对他的影响 res += a[fa[u]] + op[fa[u]]*2 ; (为什么*2好好想想)

其次:
res += (son[u] + 1) * op[u] + a[u] * 2 + b[u];
son[u] + 1 是指改变点u对它本身和其儿子的影响, 而a[u]表示儿子对它的影响, b[u]表示u的孙子对u的影响.

所以代码如下: (提醒下, 不知道为什么会T, 然后用了fastio, 直接到400ms, 读入挂真的猛)
AC Code

const int maxn = 1e5+5;
int cas=1;
int fa[maxn],son[maxn],op[maxn],a[maxn],b[maxn];
struct FastIO
{
    static const int S = 2*100;
    int wpos;
    char wbuf[S];
    FastIO() : wpos(0) {}
    inline int xchar()
    {
        static char buf[S];
        static int len = 0, pos = 0;
        if (pos==len)
            pos = 0, len = fread(buf, 1, S, stdin);
        if (pos==len) exit(0);
        return buf[pos ++];
    }
    inline int xint()
    {
        int s = 1, c = xchar(), x = 0;
        while(c<=32) c = xchar();
        if(c=='-') s = -1, c = xchar();
        for(;'0'<=c && c<='9';c=xchar()) x = x*10+c-'0';
        return x * s;
    }
    ~FastIO()
    {
        if(wpos) fwrite(wbuf, 1, wpos, stdout), wpos = 0;
    }
}io;
void solve()
{
    int n,m;
    n = io.xint(); m = io.xint();
    for(int i=1;iint u; u = io.xint();
        fa[i+1] = u;
        son[u]++;
    }
    ll ans = 0;
    for(int i=1;i<=m;i++) {
        int u; u = io.xint();
        op[u] = (op[u] + 1) % mod;
        ll res = 0;
        if(fa[u]) {
            int tmp = fa[u];
            a[tmp] = (a[tmp] + 1) % mod;
            res = (res + a[tmp] + op[tmp] + op[tmp]) % mod;
        }
        if(fa[fa[u]]) {
            int tmp = fa[fa[u]];
            b[tmp] = (b[tmp] + 1) % mod;
            res = (res + op[tmp]) % mod;
        }
        res = (res + (son[u] + 1) * op[u] + a[u] + a[u] + b[u]) % mod;
        ans = (ans + res * i % mod ) % mod;
    }
    cout << ans << endl;
}

D:
其实是一道水题, 想好是排序后对应位置当然可以使答案最优就行了, 然后是赋值, 所以可以直接替换掉前x个最小的(前提是有这么多个)就行了…..

AC Code

const int maxn = 2e5+5;
int cas=1;
int a[maxn],b[maxn];
void solve()
{
    int n,x,y;
    scanf("%d%d%d",&n,&x,&y);
    for(int i=1;i<=n;i++) {
        scanf("%d",&a[i]);
    }
    for(int i=1;i<=n;i++) {
        scanf("%d",&b[i]);
    }
    sort(a+1,a+1+n);
    sort(b+1,b+1+n);
    for(int i=1;i<=n&&i<=x;i++) {
        if(a[i]<y) a[i] = y;
    }
    sort(a+1,a+1+n);
    int ans = 0;
    for(int i=1;i<=n;i++) {
        ans = max(ans,b[i]-a[i]);
    }
    cout << ans << endl;
}

你可能感兴趣的:(比较杂的题解,想法思维题)