【jzoj4895】【三部曲】【线段树】

题目大意

因为外来的入侵,国王决定在某些城市加派士兵。所有城市初始士兵数量为0。当城市 被加派了k名士兵时。城市i的所有子城市需要被加派k+1名士兵。这些子城市的所有子城市需要被加派k+2名士兵。以此类推。当然,加派士兵的同时,国王也需要不断了解当前的情况。于是他随时可能询问以城市i为根的子树中的所有城市共被加派了多少士兵。你现在是国王的军事大臣,你能回答出国王的每个询问么?

解题思路

先按dfs序重标号,把操作拆成两个,把一段点都加上深度,把一段点都加上一个值,这样就可以用线段树维护了。

code

#include
#include
#include
#define LL long long
#define fo(i,j,k) for(LL i=j;i<=k;i++)
#define fd(i,j,k) for(LL i=j;i>=k;i--)
using namespace std;
LL const maxn=5*1e4;
LL n,p,gra,time,begin[maxn+10],to[maxn+10],next[maxn+10],dfn[maxn+10],leave[maxn+10],
dep[maxn+10],tag[maxn*4+10][3];
LL ans,sumdep[maxn*4+10],t[maxn*4+10];
void insert(LL u,LL v){
    to[++gra]=v;
    next[gra]=begin[u];
    begin[u]=gra;
}
void dfs(LL now){
    dfn[now]=++time;
    for(LL i=begin[now];i;i=next[i]){
        dep[time+1]=dep[dfn[now]]+1;
        dfs(to[i]);
    }
    leave[now]=time;
}
void retag(LL pos,LL l,LL mid,LL r){
    fo(i,1,2){
        if(i==1){
            t[pos*2]+=tag[pos][i]*sumdep[pos*2];
            t[pos*2+1]+=tag[pos][i]*sumdep[pos*2+1];
        }else{
            t[pos*2]+=tag[pos][i]*(mid-l+1);
            t[pos*2+1]+=tag[pos][i]*(r-mid);
        }
        tag[pos*2][i]+=tag[pos][i];
        tag[pos*2+1][i]+=tag[pos][i];
        tag[pos][i]=0;
    }
}
void reset(LL pos,LL l,LL r){
    LL mid=(l+r)/2;
    if(l==r)sumdep[pos]=dep[l];
    else{
        reset(pos*2,l,mid);
        reset(pos*2+1,mid+1,r);
        sumdep[pos]=sumdep[pos*2]+sumdep[pos*2+1];
    }
}
LL qury(LL pos,LL l,LL r,LL ll,LL rr){
    LL mid=(l+r)/2;
    if(l!=r)retag(pos,l,mid,r);
    if((l==ll)&&(r==rr))return t[pos];
    else if(rr<=mid)return qury(pos*2,l,mid,ll,rr);
    else if(midreturn qury(pos*2+1,mid+1,r,ll,rr);
    else return qury(pos*2,l,mid,ll,mid)+qury(pos*2+1,mid+1,r,mid+1,rr);
}
void add(LL pos,LL l,LL r,LL ll,LL rr,LL op,LL val){
    LL mid=(l+r)/2;
    if(l!=r)retag(pos,l,mid,r);
    if((l==ll)&&(r==rr)){
        tag[pos][op]+=val;
        if(op==1)t[pos]+=sumdep[pos];
        else t[pos]+=(r-l+1)*val;
        return;
    }else if(rr<=mid)add(pos*2,l,mid,ll,rr,op,val);
    else if(midpos*2+1,mid+1,r,ll,rr,op,val);
    else{
        add(pos*2,l,mid,ll,mid,op,val);
        add(pos*2+1,mid+1,r,mid+1,rr,op,val);
    }
    t[pos]=t[pos*2]+t[pos*2+1];
}
int main(){
    //freopen("truetears.in","r",stdin);
    //freopen("truetears.out","w",stdout);
    freopen("d.in","r",stdin);
    freopen("d.out","w",stdout);
    scanf("%lld%lld",&n,&p);
    fo(i,2,n){
        LL u;scanf("%lld",&u);
        insert(u,i);
    }
    dfs(1);
    reset(1,1,n);
    scanf("\n");
    fo(i,1,p){
        char ch;scanf("%c",&ch);
        if(ch=='A'){
            LL x,k;scanf("%lld%lld\n",&x,&k);
            add(1,1,n,dfn[x],leave[x],1,1);
            add(1,1,n,dfn[x],leave[x],2,k-dep[dfn[x]]);
        }else{
            LL x;scanf("%lld\n",&x);
            printf("%lld\n",qury(1,1,n,dfn[x],leave[x]));
        }
    }
    return 0;
}

你可能感兴趣的:(jzoj4895,三部曲,jzoj,数据结构)