[BZOJ2631]tree 动态树lct
2631: tree
Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 5171 Solved: 1754
[Submit][Status][Discuss]
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
对于每个/对应的答案输出一行
Sample Input
3 2
1 2
2 3
* 1 3 4
/ 1 1
1 2
2 3
* 1 3 4
/ 1 1
Sample Output
4
HINT
数据规模和约定
10%的数据保证,1<=n,q<=2000
另外15%的数据保证,1<=n,q<=5*10^4,没有-操作,并且初始树为一条链
另外35%的数据保证,1<=n,q<=5*10^4,没有-操作
100%的数据保证,1<=n,q<=10^5,0<=c<=10^4
Source
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cmath> 5 #include<cstdlib> 6 #include<algorithm> 7 #define maxn 500005 8 #define ls(x) t[x].s[0] 9 #define rs(x) t[x].s[1] 10 #define ll long long 11 #define mod 51061 12 using namespace std; 13 inline ll read() { 14 ll x=0,f=1;char ch=getchar(); 15 for(;!isdigit(ch);ch=getchar()) if(ch=='-') f=-1; 16 for(;isdigit(ch);ch=getchar()) x=x*10+ch-'0'; 17 return x*f; 18 } 19 struct data { 20 ll s[2],fa,c,a,v,sum,size; 21 data(){c=1;v=1,a=0,sum=1,size=1;} 22 bool rev; 23 }t[maxn]; 24 bool isroot(int x) {return ls(t[x].fa)!=x&&rs(t[x].fa)!=x;} 25 void pushup(int x) {t[x].sum=t[ls(x)].sum+t[rs(x)].sum+t[x].v;t[x].sum%=mod;t[x].size=t[ls(x)].size+t[rs(x)].size+1;} 26 void cal(int x,int ce,int add) { 27 t[x].sum=t[x].sum*ce+add*t[x].size;t[x].sum%=mod; 28 t[x].v=t[x].v*ce+add;t[x].v%=mod; 29 t[x].c*=ce;t[x].c%=mod; 30 t[x].a=t[x].a*ce+add;t[x].a%=mod; 31 } 32 void pushdown(int x) { 33 if(t[x].rev) { 34 swap(ls(x),rs(x)); 35 t[ls(x)].rev^=1;t[rs(x)].rev^=1;t[x].rev^=1; 36 } 37 int ce=t[x].c,add=t[x].a; 38 t[x].c=1;t[x].a=0; 39 cal(ls(x),ce,add);cal(rs(x),ce,add); 40 } 41 void rotate(int x) { 42 int y=t[x].fa,z=t[y].fa; 43 bool l=ls(y)!=x,r=l^1; 44 if(!isroot(y)) t[z].s[t[z].s[1]==y]=x; 45 t[x].fa=z;t[y].fa=x;t[y].s[l]=t[x].s[r]; 46 t[t[x].s[r]].fa=y;t[x].s[r]=y; 47 pushup(y);pushup(x); 48 } 49 void pre(int x) { 50 if(!isroot(x)) pre(t[x].fa); 51 pushdown(x); 52 } 53 void splay(int x) { 54 pre(x); 55 while(!isroot(x)) { 56 int y=t[x].fa,z=t[y].fa; 57 if(!isroot(y)){ 58 if(ls(y)==x^ls(z)==y) rotate(x); 59 else rotate(y); 60 } 61 rotate(x); 62 } 63 } 64 void access(int x) {for(int y=0;x;y=x,x=t[x].fa) {splay(x);t[x].s[1]=y;pushup(x);}} 65 void mroot(int x) {access(x);splay(x);t[x].rev^=1;} 66 void link(int x,int y) {mroot(x);t[x].fa=y;} 67 void cut(int x,int y) {mroot(x);access(y);splay(y);t[y].s[0]=t[x].fa=0;pushup(y);} 68 int n,q; 69 int main() { 70 n=read(),q=read(); 71 t[0].a=t[0].c=t[0].sum=t[0].size=0; 72 for(int i=1;i<n;i++) {int u=read(),v=read();link(u,v);} 73 for(int i=1;i<=q;i++) { 74 char ch[10];scanf("%s",ch); 75 if(ch[0]=='+') {int u=read(),v=read();mroot(u);access(v);splay(v);ll tmp=read();cal(v,1,tmp);} 76 if(ch[0]=='-') {int u=read(),v=read();cut(u,v);u=read();v=read();link(u,v);} 77 if(ch[0]=='*') {int u=read(),v=read();mroot(u);access(v);splay(v);ll tmp=read();cal(v,tmp,0);} 78 if(ch[0]=='/') {int u=read(),v=read();mroot(u);access(v);splay(v);printf("%lld\n",t[v].sum);} 79 } 80 return 0; 81 } 82 /* 83 5 100 84 1 2 1 3 3 4 3 5 85 + 4 5 3 86 / 4 5 87 * 4 5 3 88 / 4 5 89 - 3 4 4 5 90 / 3 4 91 */
O(∩_∩)O~ (*^__^*) 嘻嘻…… O(∩_∩)O哈哈~