BZOJ 3786星系探索【Splayメンテナンスdfsシーケンス】*


BZOJ 3786星系探索
Description
物理学者のCさんの研究はあるボトルネックに直面している.彼が研究しているのは星系で、この星系にはnつの星があり、そのうち1つの主星(便宜上1番星とデフォルト)があり、残りのすべての星には1つの依存星しかありません.主星は星に依存していない.我々は依存関係を以下のように定義する:星aの依存星がbであれば、星aが星bに依存するb.また、依存関係には伝達性があり、すなわち星aが星bに依存し、星bが星cに依存すると、星aが星cに依存するc.この神秘的な星系の中で、小Cはその性質を初歩的に探究し、星間の依存関係は無環であることを発見した.そして、星aから直接その依存星bに到達するしかないb.各星iにはエネルギー係数wiがある.Cさんは何度か実験をしたいと思っています.i回目の実験では、宇宙船から星diに初期エネルギーが0のエネルギー収集器を打ち上げ、エネルギー収集器は星diから主星に向かい、沿道の各星のエネルギーの一部を収集します.エネルギーを収集するのはこの星のエネルギー係数に等しいです.しかし、星系の構成は変わらないわけではありません.ある時、星系はいくつかの複雑な原因で変化する可能性があります.ある星のエネルギーが励起されると、それに依存するすべての星と彼自身のエネルギー係数が一定値を増加させることがあります.ある時、ある星の依存星が変化する可能性もあるが、変化後に依存関係を満たすには無環である.現在、小Cは時刻0時の各星のエネルギー係数と、各星(主星を除く)の依存星を測定している.次のm時刻、各時刻にいくつかのイベントが発生します.その中でCさんは何回か実験を行うかもしれませんが、彼の実験のたびに、今回の実験エネルギー収集器の最終エネルギーはいくらなのか教えてください.
Input
最初の行の整数nは、星系の星数を表す.次に、n−1行の各行の整数は、それぞれ星2−nの依存星番号を表す.次のn行の整数は、各星の時刻0における初期エネルギー係数wiを表す.次の行には、イベントの合計数を表す整数mがあります.イベントには、次の3つのタイプがあります.(1)「Qdi」は、小Cが実験を開始し、コレクターの初期位置が星diであることを示す.(2)「Cxi yi」は、星xiの依存星が星yiになることを示す.(3)「Fpi qi」は星piのエネルギー励起を表し、定数はqiである.
Output
各イベントタイプQのイベントについて,今回の実験のコレクタの最終エネルギーを表す1行1整数を出力した.
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=0 w i>=0
tips:
罪悪な卡常、本机の20 s-はBZOJの上でTを要して、BZOJの评测机はジャガイモですか??
BZOJは評価機を交換することを強くお勧めします
どうせコードが正しいんだから、カードとかは関係ないだろう.
まず、この構造がツリー構造であることがわかります.次に、ポイントからルートノードへのパス権値をクエリーし、ノードの父親を変更し、サブツリーに値を追加します.
最初はLCTをやりたかったのですが、LCTを見つけてサブツリー情報をメンテナンスするのは難しそう?
そこで考えてみると、dfsシーケンスの優美な性質を思い浮かべると、求和を接頭辞和に変換し、修正父を区間平行移動に変換し、サブ区間に値を加えて直接入桟ノードと出桟ノードの間の数に値を加えることができる(区間修正?)そしてSplay
非回転Treap定数が大きいと聞いて書いてなかったのですが、まさかSplayも異常かな...
このコードは通れないよ
#include
using namespace std;
#define N 200010
#define LL long long
#define pi pair
inline int read(){
    int ans=0,w=1;char c=getchar();
    while(!isdigit(c)&&c!='-')c=getchar();
    if(c=='-')w=-1,c=getchar();
    while(isdigit(c))ans=(ans<<1)+(ans<<3)+c-'0',c=getchar();
    return ans*w;
}
inline void print(LL x){
    if(x<0){putchar('-');x=-x;}
    if(x>9)print(x/10);
    putchar((x-(x/10)*10)+'0');
} 
struct Edge{int v,next;}E[N];
int head[N]={0},tot=0;
int n,q,id[N],dfn=0;
int w[N];
pi st[N];
inline void add(int u,int v){
    E[++tot]=(Edge){v,head[u]};
    head[u]=tot;
}
inline void dfs(int u,int fa){
    id[++dfn]=u;
    st[dfn]=(pi){w[u],1};
    for(int i=head[u];i;i=E[i].next)
        if(E[i].v!=fa)dfs(E[i].v,u);
    id[++dfn]=u+n;
    st[dfn]=(pi){-w[u],-1};
}
int root,fa[N],son[N][2],cnt=0;
int tag[N],siz[N],num[N],typ[N];
LL sum[N],val[N];
inline void pushup(int t){
    sum[t]=sum[son[t][0]]+sum[son[t][1]]+val[t];
    siz[t]=siz[son[t][0]]+siz[son[t][1]]+1;
    num[t]=num[son[t][0]]+num[son[t][1]]+typ[t];
}
inline void pushnow(int t,LL vl){
    tag[t]+=vl;
    if(typ[t]>0)val[t]+=vl;
    else val[t]-=vl;
    sum[t]+=vl*num[t];
}
inline void pushdown(int t){
    if(fa[t])pushdown(fa[t]);
    if(tag[t]){
        pushnow(son[t][0],tag[t]);
        pushnow(son[t][1],tag[t]);
        tag[t]=0;
    }
}
inline bool Son(int t){return son[fa[t]][1]==t;}
inline void rotate(int t){
    int f=fa[t],g=fa[f];
    bool a=Son(t),b=a^1;
    if(g)son[g][Son(f)]=t;fa[t]=g;
    son[f][a]=son[t][b];fa[son[f][a]]=f;
    son[t][b]=f;fa[f]=t;
    pushup(f);pushup(t);
}
inline void splay(int t,int tp){
    if(!t)return;
    pushdown(t);
    while(fa[t]!=tp){
        int f=fa[t];
        if(fa[f]!=tp){
            if(Son(t)^Son(f))rotate(t);
            else rotate(f);
        }
        rotate(t);
    }
    if(!tp)root=t;
}
inline int build(int l,int r){
    if(l>r)return 0;
    int mid=(l+r)>>1,t=id[mid];
    val[t]=sum[t]=st[mid].first;
    num[t]=typ[t]=st[mid].second;
    siz[t]=1;tag[t]=0;
    if(l==r)return t;
    fa[son[t][0]=build(l,mid-1)]=t;
    fa[son[t][1]=build(mid+1,r)]=t;
    pushup(t);
    return t;
}
inline int pre(int pos){
    int t=son[pos][0];
    while(son[t][1])t=son[t][1];
    return t;
}
inline int nxt(int pos){
    int t=son[pos][1];
    while(son[t][0])t=son[t][0];
    return t;
} 
inline void modify(int l,int r,LL vl){
    int ll=pre(l),rr=nxt(r);
    splay(ll,0);
    splay(rr,root);
    pushnow(son[son[root][1]][0],vl);
}
inline LL query(int pos){
    splay(pos,0);
    return sum[son[pos][0]]+val[pos];
}
inline void change(int pos,int father){
    int lx=pre(pos),rx=nxt(pos+n);
    splay(lx,0);
    splay(rx,lx);
    int t=son[rx][0];
    fa[t]=0;son[rx][0]=0;
    int lf=nxt(father);
    splay(father,0);
    splay(lf,father);
    son[lf][0]=t;fa[t]=lf;
    pushup(lf);
    pushup(father);
}
int main(){
    n=read();
    for(int i=2;i<=n;i++){
        int x=read();
        add(i,x);add(x,i);
    }
    for(int i=1;i<=n;i++)w[i]=read();
    dfs(1,0);
    id[0]=n*2+1;st[0]=(pi){0,1};
    id[dfn+1]=n*2+2;st[dfn+1]=(pi){0,-1};
    root=build(0,dfn+1);
    int m=read();
    while(m--){
        char c[5];
        scanf("%s",c);
        if(c[0]=='Q'){
            int x=read();
            print(query(x));
            printf("
"
); }else if(c[0]=='C'){ int x=read(),y=read(); change(x,y); }else{ int x=read(),y=read(); modify(x,x+n,y); } } return 0; }