ccz181078

  博客园 :: 首页 :: 博问 :: 闪存 :: 新随笔 :: 联系 :: :: 管理 ::

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\n",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;
}

 

posted on 2017-02-26 21:27  nul  阅读(191)  评论(0编辑  收藏  举报