BZOJ_2631_tree_LCT
Description
A tree with n points, the initial weight of each point is 1. There are q operations on this tree, and each operation is one of the following four operations:
+ uvc: add the natural number c to the weights of the points on the path from u to v;
- u1 v1 u2 v2: add the original value in the tree Some edges (u1, v1) are deleted, and a new edge (u2, v2) is added to ensure that it is still a tree after the operation;
* uvc: Multiply the weights of the points on the path from u to v by the natural number c ;
/uv: ask the weight sum of the points on the path from u to v, and find the remainder of the answer for 51061.
Input
Next n-1 lines each contains two positive integers u, v, describing the tree
Next q lines, each describing an operation
Output
Sample Input
1 2
2 3
* 1 3 4
/ 1 1
Sample Output
HINT
Data size and agreement
10% data guarantee, 1<=n, q<=2000
another 15% data guarantee, 1<=n, q<=5*10^4, no - operation, and the initial tree is a chain
Another 35% data guarantee, 1<=n, q<=5*10^4, no-operation
100% data guarantee, 1<=n, q<=10^5, 0<=c<=10^ 4
LCT template questions. Pay attention to the order in which multiplication and addition are downloaded.
Code:
#include <stdio.h> #include <string.h> #include <algorithm> using namespace std; #define N 100050 #define mod 51061 #define ls ch[p][0] #define rs ch[p][1] #define get(x) (ch[f[x]][1]==x) typedef unsigned int ui; int n,m,ch[N][2],f[N],rev[N]; ui sum [N], mul [N], add [N], siz [N], val [N]; char opt[10]; inline bool isrt(int x) { return ch[f[x]][0]!=x&&ch[f[x]][1]!=x; } void pushdown(int p) { if(mul[p]!=1) { ui u = mul [p]; sum [ls] = sum [ls] * u% mod; mul [ls] = mul [ls] * u% mod; add [ls] = add [ls] * u% mod; val [ls] = val [ls] * u% mod; sum[rs]=sum[rs]*u%mod; mul[rs]=mul[rs]*u%mod; add[rs]=add[rs]*u%mod; val[rs]=val[rs]*u%mod; mul [p] = 1; } if(add[p]) { ui d=add[p]; sum [ls] = (sum [ls] + siz [ls] * d% mod)% mod; add [ls] = (add [ls] + d)% mod; val [ls] = (val [ls] + d)% mod; sum[rs]=(sum[rs]+siz[rs]*d%mod)%mod; add[rs]=(add[rs]+d)%mod; val[rs]=(val[rs]+d)%mod; add[p]=0; } if(rev[p]) { swap(ch[ls][0],ch[ls][1]); swap(ch[rs][0],ch[rs][1]); rev[ls]^=1; rev[rs]^=1; rev[p]=0; } /*cal(ls , add[p] , mul[p] , rev[p]); cal(rs , add[p] , mul[p] , rev[p]); add[p] = rev[p] = 0 , mul[p] = 1;*/ } void pushup(int p) { you [p] = you [ls] + you [rs] +1; sum[p]=(sum[ls]+sum[rs]+val[p])%mod; } void update(int p) { if(!isrt(p)) update(f[p]); pushdown(p); } void rotate(int x) { int y=f[x],z=f[y],k=get(x); if(!isrt(y)) ch[z][ch[z][1]==y]=x; ch[y][k]=ch[x][!k]; f[ch[y][k]]=y; ch[x][!k]=y; f[y]=x; f[x]=z; pushup(y); pushup(x); } void splay(int x) { update(x); for(int fa;fa=f[x],!isrt(x);rotate(x)) if(!isrt(fa)) rotate(get(fa)==get(x)?fa:x); } void access(int p) { int t=0; while(p) splay(p),rs=t,pushup(p),t=p,p=f[p]; } void makeroot (int p) { access(p); splay(p); swap(ls,rs); rev[p]^=1; } void link(int x,int p) { makeroot (x); f [x] = p; } void cut(int x,int p) { makeroot(x); access(p); splay(p); ls=f[x]=0; } void split(int x,int p) { makeroot(x); access(p); splay(p); } int main() { scanf("%d%d",&n,&m); int i,x,y,z,w; for(i=1;i<=n;i++) val[i]=mul[i]=siz[i]=sum[i]=1; for(i=1;i<n;i++) { scanf("%d%d",&x,&y); link(x,y); } for(i=1;i<=m;i++) { scanf("%s%d%d",opt,&x,&y); int p=y; if(opt[0]=='+') { scanf("%d",&z); split(x,p); sum[p]=(sum[p]+siz[p]*z%mod)%mod; val[p]=(val[p]+z)%mod; add[p]=(add[p]+z)%mod; //cal(p,z,1,0); }else if(opt[0]=='-') { scanf("%d%d",&z,&w); cut(x,y); link(z,w); }else if(opt[0]=='*') { scanf("%d",&z); split(x,p); sum[p]=sum[p]*z%mod; val[p]=val[p]*z%mod; add[p]=add[p]*z%mod; mul [p] = mul [p] * z% mod; //cal(p,0,z,0); }else { split(x,p); printf("%u\n",sum[p]); } } }