ccz181078

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

Description

最初有一棵带点权的树。
给出下列操作:
1 x y z  在x为根的树里,y到根路径链加z
2 x y z  x~y链上点权都修改为z
3 x y    在x为根的树里,对y子树的点权求和 
4 x y    x~y链上取点权max
5 x y    x~y链上求点权和
6 x y    连接 x~y
7 x y    断开 x~y 

保证操作1~5上x和y在同一棵树上。
保证6和7操作合法(即操作前后都是森林)。

由于子树信息可减,可以用lct维护

#include<bits/stdc++.h>
typedef long long i64;
const int N=200007;
char ib[15000007],*ip=ib;
int _(){
    int x=0;
    while(*ip<48)++ip;
    while(*ip>47)x=x*10+*ip++-48;
    return x;
}
void pr(i64 x){printf("%lld\n",x);}
i64 max(i64 a,i64 b){return a>b?a:b;}
#define lc c[0]
#define rc c[1]
struct node{
    node*c[2],*f;
    int sz,rv,fil;
    i64 v,a,mx,s1,s2;
    void _rv();
    void _a(i64);
    void _fil(int);
    void dn(){
        if(rv)lc->_rv(),rc->_rv(),rv=0;
        if(fil)lc->_fil(fil),rc->_fil(fil),fil=0;
        if(a)lc->_a(a),rc->_a(a),a=0;
    }
    void up(){
        mx=max(v,max(lc->mx,rc->mx));
        s1=v+lc->s1+rc->s1;
        sz=1+lc->sz+rc->sz;
    }
    int wc(){return this==f->rc;}
    bool nrt(){return this==f->lc||this==f->rc;}
}ns[N],*stk[N];
void node::_rv(){if(this!=ns)rv^=1,std::swap(lc,rc);}
void node::_a(i64 x){if(this!=ns)a+=x,v+=x,mx+=x,s1+=sz*x;}
void node::_fil(int x){if(this!=ns)a=0,v=mx=x,s1=i64(sz)*x,fil=x;}
int n,m,es[N*2],enx[N*2],e0[N],ep=2;
void rot(node*x){
    node*f=x->f,*g=f->f;
    int d=x->wc();
    if(f->nrt())g->c[f->wc()]=x;
    x->f=g;
    i64 t=f->s2;
    f->s2-=x->s2-x->c[d^1]->s2;
    x->s2=t;
    (f->c[d]=x->c[d^1])->f=f;
    (x->c[d^1]=f)->f=x;
    f->up();
}
void dns(node*a){
    int stp=0;
    for(;a!=ns;stk[++stp]=a,a=a->f);
    while(stp)stk[stp--]->dn();
}
void sp(node*x){
    while(x->nrt()){
        node*f=x->f;
        if(f->nrt())rot(f->wc()==x->wc()?f:x);
        rot(x);
    }
}
void push(node*x,node*y){
    y->f=x;
    x->s2+=y->s1+y->s2;
}
void acs(node*x){
    node*x0=x;
    dns(x);
    for(node*y=ns;x!=ns;y=x,x=x->f){
        sp(x);
        x->s2+=x->rc->s1-y->s1;
        x->rc=y;
        x->up();
    }
    sp(x0);
    x0->up();
}
void mrt(node*x){acs(x),x->_rv();}
void get(node*x,node*y){mrt(x),acs(y);}
void f1(int w,int pa){
    for(int i=e0[w];i;i=enx[i]){
        int u=es[i];
        if(u!=pa){
            f1(u,w);
            push(ns+w,ns+u);
        }
    }
}
int main(){
    fread(ib,1,sizeof(ib),stdin);
    n=_();
    ns[0]=(node){ns,ns,ns,0,0,0,0,0,0,0,0};
    for(int i=1;i<=n;++i){
        int x=_();
        ns[i]=(node){ns,ns,ns,1,0,0,x,0,x,x,0};
    }
    for(int i=2,a,b;i<=n;++i){
        a=_(),b=i;
        es[ep]=b;enx[ep]=e0[a];e0[a]=ep++;
        es[ep]=a;enx[ep]=e0[b];e0[b]=ep++;
    }
    f1(1,0);
    for(m=_();m;--m){
        int o=_();
        node*x=ns+_(),*y=ns+_();
        get(x,y);
        if(o==1)y->_a(_());
        else if(o==2)y->_fil(_());
        else if(o==3)pr(y->v+y->s2-y->lc->s2);
        else if(o==4)pr(y->mx);
        else if(o==5)pr(y->s1);
        else if(o==6)push(y,x);
        else{
            x->f=y->lc=ns;
            y->s2-=x->s2;
            y->up();
        }
    }
    return 0;
}
View Code

 

posted on 2017-09-13 09:42  nul  阅读(172)  评论(0编辑  收藏  举报