1. 程式人生 > >BZOJ_3786_星系探索_splay維護出棧入棧序

BZOJ_3786_星系探索_splay維護出棧入棧序

類型 else out val long 每一個 har 維護 收集

BZOJ_3786_星系探索_splay維護出棧入棧序

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的事件,輸出一行一個整數,表示此次實驗的收集器最終能量。

Sample Input

3
1
1
4 5 7
5
Q 2
F 1 3
Q 2
C 2 3
Q 2

Sample Output

9
15
25

HINT

n<=100000,m<=300000,1<di,xi<=n,wi,qi<=100000.保證操作合法。註意w_i>=0


考慮用splay維護出棧入棧序,這樣我們求前綴和就是點到根路徑的權值和了。

換根操作也比較容易實現,因為子樹對應著一段區間,直接移動子樹即可。

就是子樹加不太好做,因為是加點權,不包含系數。

於是我們再維護出有多少個正數有多少個負數即可。

代碼:

#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long ll;
#define N 200050
#define ls ch[p][0]
#define rs ch[p][1]
#define get(x) (ch[f[x]][1]==x)
int head[N],to[N],nxt[N],cnt,ch[N][2],f[N],rt,n,m,tot,dfn[N],siz[N],son[N];
int zc[N],fc[N],a[N],type[N],val[N],w[N],fa[N];
ll sum[N];
int del[N];
char pbuf[100000],*pp=pbuf;
__attribute__((optimize("-O3")))void push(const char ch) {
    if(pp-pbuf==100000) fwrite(pbuf,1,100000,stdout),pp=pbuf;
    *pp++=ch;
}
__attribute__((optimize("-O3")))void write(ll x) {
    static int sta[50];
    int top=0;
    do{sta[++top]=x%10,x/=10;}while(x);
    while(top) push(sta[top--]+‘0‘);
    push(‘\n‘);
}
__attribute__((optimize("-O3")))inline char nc() {
    static char buf[100000],*p1,*p2;
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
__attribute__((optimize("-O3")))int rd() {
    int x=0; char s=nc();
    while(s<‘0‘||s>‘9‘) s=nc();
    while(s>=‘0‘&&s<=‘9‘) x=(x<<3)+(x<<1)+s-‘0‘,s=nc();
    return x;
}
__attribute__((optimize("-O3")))char rc() {
    char s=nc();
    while(s!=‘Q‘&&s!=‘C‘&&s!=‘F‘) s=nc();
    return s;
}
__attribute__((optimize("-O3")))void give(int p,int v) {
    val[p]+=v; del[p]+=v; sum[p]+=1ll*(zc[p]-fc[p])*v;
}
__attribute__((optimize("-O3")))void pushup(int p) {
    if(!p) return ;
    siz[p]=1;
    zc[p]=fc[p]=0;
    if(type[p]==1) zc[p]=1;
    else if(type[p]==-1) fc[p]=1;
    sum[p]=val[p]*type[p];
    siz[p]+=siz[ls],sum[p]+=sum[ls],zc[p]+=zc[ls],fc[p]+=fc[ls];
    siz[p]+=siz[rs],sum[p]+=sum[rs],zc[p]+=zc[rs],fc[p]+=fc[rs];
}
__attribute__((optimize("-O3")))void pushdown(int p) {
    if(del[p]) {
        if(ls) give(ls,del[p]);
        if(rs) give(rs,del[p]);
        del[p]=0;
    }
}
__attribute__((optimize("-O3")))void rotate(int x) {
    int y=f[x],z=f[y],k=get(x);
    ch[y][k]=ch[x][!k]; f[ch[y][k]]=y;
    ch[x][!k]=y; f[y]=x; f[x]=z;
    if(z) ch[z][ch[z][1]==y]=x;
    if(rt==y) rt=x;
    pushup(y); pushup(x);
}
__attribute__((optimize("-O3")))void update(int p,int y) {
    if(f[p]!=y) update(f[p],y);
    pushdown(p);
}
__attribute__((optimize("-O3")))void splay(int x,int y) {
    update(x,y);
    for(int d;(d=f[x])!=y;rotate(x))
        if(f[d]!=y)
            rotate(get(x)==get(d)?d:x);
}
__attribute__((optimize("-O3")))inline void add(int u,int v) {
    to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt;
}
__attribute__((optimize("-O3")))void dfs(int x) {
    int i;a[++tot]=x; type[tot+1]=1; dfn[x]=tot+1; val[tot+1]=w[x];
    for(i=head[x];i;i=nxt[i]) {
        f[to[i]]=x;
        dfs(to[i]);
    }
    a[++tot]=x; type[tot+1]=-1; son[x]=tot+1; val[tot+1]=w[x];
}
__attribute__((optimize("-O3")))void build(int fa,int l,int r) {
    if(l>r) return ;
    int mid=(l+r)>>1;
    f[mid]=fa;
    ch[fa][mid>fa]=mid;
    build(mid,l,mid-1);
    build(mid,mid+1,r);
    pushup(mid);
}
__attribute__((optimize("-O3")))int pre() {
    int p=ch[rt][0];
    for(;rs;p=rs) pushdown(p);
    return p;
}
__attribute__((optimize("-O3")))int suc() {
    int p=ch[rt][1];
    for(;ls;p=ls) pushdown(p);
    return p;
}
__attribute__((optimize("-O3")))void huan(int x,int y) {
    splay(dfn[x],0); int p2=pre();
    splay(son[x],0); int p4=suc();
    splay(p2,0); splay(p4,p2);
    int p5=ch[p4][0]; f[p5]=0; ch[p4][0]=0;
    pushup(p4); pushup(p2);
    int p6=dfn[y];
    splay(p6,0); int p7=suc();
    splay(p7,p6);
    ch[p7][0]=p5; f[p5]=p7;
    pushup(p5); pushup(p7); pushup(p6);
}
__attribute__((optimize("-O3")))int find(int x) {
    int p=rt;
    while(1) {
        pushdown(p);
        if(x<=siz[ls]) p=ls;
        else {
            x-=siz[ls]+1;
            if(!x) return p;
            p=rs;
        }
    }
}
__attribute__((optimize("-O3")))void print() {
    int i,p;
    for(i=1;i<=tot+2;i++) {
        p=find(i);
        printf("i=%d,p=%d,val[p]=%d,f[p]=%d,zc[p]=%d,fc[p]=%d\n",i,p,val[p],f[p],zc[p],fc[p]);
    }
}
__attribute__((optimize("-O3")))int main() {
    n=rd();
    register int i,x,y,p;
    for(i=2;i<=n;i++) {
        x=rd();
        add(x,i);
    }
    for(i=1;i<=n;i++) w[i]=rd();
    dfs(1);
    build(0,1,tot+2);
    rt=(tot+3)>>1;
    m=rd();
    char opt;
    while(m--) {
        opt=rc(); x=rd();
        if(opt==‘Q‘) {
            x=dfn[x]; 
            // splay(x,0); p=suc();
            // splay(1,0); splay(p,1);
            splay(1,0);
            splay(x,1); 
            for(p=ch[x][1];ls;p=ls);
            splay(p,1);
            write(sum[ls]);
        }else if(opt==‘C‘) {
            y=rd();
            // scanf("%d",&y);
            if(fa[x]!=y) huan(x,y),fa[x]=y;
        }else {
            y=rd();
            // scanf("%d",&y);
            int q=dfn[x]; 
            splay(q,0); p=pre();
            int t1=p;
            q=son[x];
            splay(q,0); p=suc();
            splay(t1,0); splay(p,t1);
            give(ls,y);
        }
    }
    fwrite(pbuf,1,pp-pbuf,stdout);
}

BZOJ_3786_星系探索_splay維護出棧入棧序