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; }