Description
物理学家小C的研究正遇到某个瓶颈。
他正在研究的是一个星系,这个星系中有n个星球,其中有一个主星球(方便起见我们默认其为1号星球),其余的所有星球均有且仅有一个依赖星球。主星球没有依赖星球。
我们定义依赖关系如下:若星球a的依赖星球是b,则有星球a依赖星球b.此外,依赖关系具有传递性,即若星球a依赖星球b,星球b依赖星球c,则有星球a依赖星球c.
对于这个神秘的星系中,小C初步探究了它的性质,发现星球之间的依赖关系是无环的。并且从星球a出发只能直接到达它的依赖星球b.
每个星球i都有一个能量系数wi.小C想进行若干次实验,第i次实验,他将从飞船上向星球di发射一个初始能量为0的能量收集器,能量收集器会从星球di开始前往主星球,并收集沿途每个星球的部分能量,收集能量的多少等于这个星球的能量系数。
但是星系的构成并不是一成不变的,某些时刻,星系可能由于某些复杂的原因发生变化。
有些时刻,某个星球能量激发,将使得所有依赖于它的星球以及他自己的能量系数均增加一个定值。还有可能在某些时刻,某个星球的依赖星球会发生变化,但变化后依然满足依赖关系是无环的。
现在小C已经测定了时刻0时每个星球的能量系数,以及每个星球(除了主星球之外)的依赖星球。接下来的m个时刻,每个时刻都会发生一些事件。其中小C可能会进行若干次实验,对于他的每一次实验,请你告诉他这一次实验能量收集器的最终能量是多少。
Input
第一行一个整数n,表示星系的星球数。
接下来n-1行每行一个整数,分别表示星球2-n的依赖星球编号。
接下来一行n个整数,表示每个星球在时刻0时的初始能量系数wi.
接下来一行一个整数m,表示事件的总数。
事件分为以下三种类型。
(1)"Q di"表示小C要开始一次实验,收集器的初始位置在星球di.
(2)"C xi yi"表示星球xi的依赖星球变为了星球yi.
(3)"F pi qi"表示星球pi能量激发,常数为qi.
Output
对于每一个事件类型为Q的事件,输出一行一个整数,表示此次实验的收集器最终能量。
用平衡树维护树对应的括号序列,子树修改对应区间覆盖,点到根的路径对应区间求和,可以通过标记维护
#include<cstdio> const int N=100007; #define G *++ptr #define lc ch][0 #define rc ch][1 #define fa ch][2 #define val ch][3 #define sum ch][4 #define at ss][0 #define st ss][1 #define vt ss][2 char buf[N*100],*ptr=buf-1; int _(){ int x=0,c=G,f=1; while(c<48)c=='-'&&(f=-1),c=G; while(c>47)x=x*10+c-48,c=G; return x*f; } int _c(){ int c=G; while(c<33)c=G; return c; } typedef long long i64; int n,ch[N*2][5],nx[N],r1,r2,r3; i64 ss[N*2][3]; void adds(int x,i64 a){ if(!x)return; x[at]+=a; x[vt]+=x[val]*a; x[st]+=x[sum]*a; } void dn(int x){ if(x[at]){ adds(x[lc],x[at]); adds(x[rc],x[at]); x[at]=0; } } void up(int x){ int l=x[lc],r=x[rc]; x[sum]=x[val]+l[sum]+r[sum]; x[st]=x[vt]+l[st]+r[st]; } void rot(int w){ int f=w[fa],g=f[fa],d=(w!=f[lc]); dn(f);dn(w); if(g)g[ch][g[lc]!=f]=w; w[fa]=g; (f[ch][d]=w[ch][d^1])[fa]=f; (w[ch][d^1]=f)[fa]=w; up(f);up(w); } void sp(int x){ while(x[fa]){ int f=x[fa]; if(f[fa])rot((x==f[lc])==(f==f[fa][lc])?f:x); rot(x); } } void ct_l(int w,int&a,int&b){sp(w);a=w[lc];b=w;dn(w);a[fa]=w[lc]=0;up(w);} void ct_r(int w,int&a,int&b){sp(w);b=w[rc];a=w;dn(w);b[fa]=w[rc]=0;up(w);} int mg(int a,int b){ if(!a||!b)return a|b; while(b[lc])b=b[lc]; sp(b); dn(b);(b[lc]=a)[fa]=b;up(b); return b; } void lk(int x,int y){ x<<=1;y<<=1; ct_r(y,r1,r2); sp(x); mg(mg(r1,x),r2); } void ct(int x){ x<<=1; ct_l(x,r1,r2); ct_r(x^1,r2,r3); mg(r1,r3); } int main(){ buf[fread(buf,1,sizeof(buf),stdin)]=0; n=_(); for(int i=2;i<=n;++i)nx[i]=_(); for(int i=1;i<=n;++i){ int l=i<<1,r=l^1; l[vt]=_(); r[vt]=r[st]=-l[vt]; l[val]=1; r[sum]=r[val]=-1; (l[rc]=r)[fa]=l; } for(int i=2;i<=n;++i)lk(i,nx[i]); for(int q=_(),o;q;--q){ o=_c(); if(o=='Q'){ int w=_()<<1; sp(w); printf("%lld ",w[lc][st]+w[vt]); }else if(o=='C'){ int x=_(),y=_(); ct(x);lk(x,y); }else{ int x=_()<<1,y=_(); ct_l(x,r1,r2); ct_r(x^1,r2,r3); sp(x); adds(x,y); mg(r1,mg(x,r3)); } } return 0; }