题目大意
因为外来的入侵,国王决定在某些城市加派士兵。所有城市初始士兵数量为0。当城市 被加派了k名士兵时。城市i的所有子城市需要被加派k+1名士兵。这些子城市的所有子城市需要被加派k+2名士兵。以此类推。当然,加派士兵的同时,国王也需要不断了解当前的情况。于是他随时可能询问以城市i为根的子树中的所有城市共被加派了多少士兵。你现在是国王的军事大臣,你能回答出国王的每个询问么?
解题思路
先按dfs序重标号,把操作拆成两个,把一段点都加上深度,把一段点都加上一个值,这样就可以用线段树维护了。
code
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;
}