Description
一棵n个点的树,每个点的初始权值为1。对于这棵树有q个操作,每个操作为以下四种操作之一:
+ u v c:将u到v的路径上的点的权值都加上自然数c;
- u1 v1 u2 v2:将树中原有的边(u1,v1)删除,加入一条新边(u2,v2),保证操作完之后仍然是一棵树;
* u v c:将u到v的路径上的点的权值都乘上自然数c;
/ u v:询问u到v的路径上的点的权值和,求出答案对于51061的余数。
Input
第一行两个整数n,q
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作
Output
对于每个/对应的答案输出一行
lct模板题。。
#include<cstdio> #include<algorithm> typedef unsigned int u32; const int P=51061; char buf[10000007],*ptr=buf-1; int _(){ int x=0,c=*++ptr; while(c<48)c=*++ptr; while(c>47)x=x*10+c-48,c=*++ptr; return x; } int _c(){ int c=*++ptr; while(c<33)c=*++ptr; return c; } #define lc ch][0 #define rc ch][1 #define fa ch][2 #define rev ch][3 #define K ch][4 #define B ch][5 #define sum ch][6 #define val ch][7 #define sz ch][8 u32 ch[100007][9]; int n,q; void revs(u32 x){ if(!x)return; x[rev]^=1; std::swap(x[lc],x[rc]); } void adds(u32 x,u32 a){ if(!x)return; x[B]=(x[B]+a)%P; x[val]=(x[val]+a)%P; x[sum]=(x[sum]+a*x[sz])%P; } void muls(u32 x,u32 a){ if(!x)return; x[K]=x[K]*a%P; x[B]=x[B]*a%P; x[val]=x[val]*a%P; x[sum]=x[sum]*a%P; } void dn(u32 x){ u32 l=x[lc],r=x[rc]; if(x[rev])revs(l),revs(r),x[rev]=0; if(x[K]!=1)muls(l,x[K]),muls(r,x[K]),x[K]=1; if(x[B])adds(l,x[B]),adds(r,x[B]),x[B]=0; } void up(u32 x){ u32 l=x[lc],r=x[rc]; x[sum]=(l[sum]+r[sum]+x[val])%P; x[sz]=(l[sz]+r[sz]+1)%P; } bool nrt(u32 x){ return x==x[fa][lc]||x==x[fa][rc]; } void rot(u32 x){ u32 f=x[fa],g=f[fa],d=(x==f[rc]); dn(f),dn(x); if(nrt(f))g[ch][g[rc]==f]=x; x[fa]=g; (f[ch][d]=x[ch][d^1])[fa]=f; (x[ch][d^1]=f)[fa]=x; up(f),up(x); } void sp(u32 x){ while(nrt(x)){ int f=x[fa]; if(nrt(f))rot((x==f[lc])==(f==f[fa][lc])?f:x); rot(x); } } int acs(u32 x){u32 y=0;for(;x;sp(x),dn(x),x[rc]=y,up(x),y=x,x=x[fa]);return y;} void mrt(u32 x){revs(acs(x));} void lk(u32 x,u32 y){mrt(x);sp(x);x[fa]=y;} void ct(u32 x,u32 y){mrt(x);acs(y);sp(y);dn(y),x[fa]=y[lc]=0,up(y);} int get(u32 x,u32 y){mrt(x);return acs(y);} int main(){ buf[fread(buf,1,sizeof(buf),stdin)]=0; n=_();q=_(); for(int i=1;i<=n;++i)i[K]=i[sum]=i[sz]=i[val]=1; for(int i=1,a,b;i<n;++i){ a=_();b=_(); lk(a,b); } while(q--){ int o=_c(),x; if(o=='+'){ x=get(_(),_());adds(x,_()); }else if(o=='-'){ ct(_(),_());lk(_(),_()); }else if(o=='*'){ x=get(_(),_());muls(x,_()); }else{ x=get(_(),_());printf("%d\n",x[sum]); } } return 0; }