2631: tree
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
有加有乘,在平衡树上的操作和在线段树上的操作是一样的。。。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<iostream> 2 #include<cstdlib> 3 #include<cmath> 4 #include<cstring> 5 #include<cstdio> 6 #include<algorithm> 7 #include<string> 8 #include<map> 9 #include<queue> 10 #include<vector> 11 #include<set> 12 #define inf 1000000000 13 #define maxn 100000+5 14 #define maxm 200000+5 15 #define eps 1e-10 16 #define ll long long 17 #define mod 51061 18 #define for0(i,n) for(int i=0;i<=(n);i++) 19 #define for1(i,n) for(int i=1;i<=(n);i++) 20 #define for2(i,x,y) for(int i=(x);i<=(y);i++) 21 #define for3(i,x,y) for(int i=(x);i>=(y);i--) 22 #define for4(i,x) for(int i=head[x],y=e[i].go;i;i=e[i].next,y=e[i].go) 23 using namespace std; 24 int read(){ 25 int x=0,f=1;char ch=getchar(); 26 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 27 while(ch>='0'&&ch<='9'){x=10*x+ch-'0';ch=getchar();} 28 return x*f; 29 } 30 unsigned int fa[maxn],c[maxn][2],sta[maxn],m,n,s[maxn],head[maxn],tot; 31 unsigned int add[maxn],mul[maxn],sum[maxn],v[maxn],top; 32 bool rev[maxn]; 33 struct edge{ 34 int go,next; 35 }e[maxm]; 36 void insert(int u,int v){ 37 e[++tot].go=v;e[tot].next=head[u];head[u]=tot; 38 e[++tot].go=u;e[tot].next=head[v];head[v]=tot; 39 } 40 bool isroot(int x){ 41 return c[fa[x]][0]!=x&&c[fa[x]][1]!=x; 42 } 43 void pushup(int x){ 44 s[x]=s[c[x][0]]+s[c[x][1]]+1; 45 sum[x]=(sum[c[x][0]]+sum[c[x][1]]+v[x])%mod; 46 } 47 void rotate(int x){ 48 int y=fa[x],z=fa[y],l=(c[y][1]==x),r=l^1; 49 if(!isroot(y))c[z][c[z][1]==y]=x; 50 fa[x]=z;fa[y]=x;fa[c[x][r]]=y; 51 c[y][l]=c[x][r];c[x][r]=y; 52 pushup(y);pushup(x); 53 } 54 void update(int x,int y,int z){ 55 if(!x)return; 56 add[x]=(add[x]*z+y)%mod;mul[x]=(mul[x]*z)%mod; 57 sum[x]=(sum[x]*z+s[x]*y)%mod;v[x]=(v[x]*z+y)%mod; 58 59 } 60 void pushdown(int x){ 61 if(rev[x]){ 62 rev[x]^=1;rev[c[x][0]]^=1;rev[c[x][1]]^=1; 63 swap(c[x][0],c[x][1]); 64 } 65 int l=c[x][0],r=c[x][1]; 66 update(l,add[x],mul[x]);update(r,add[x],mul[x]); 67 add[x]=0;mul[x]=1; 68 } 69 void splay(int x){ 70 int top=0;sta[++top]=x; 71 for(int y=x;!isroot(y);y=fa[y])sta[++top]=fa[y]; 72 for(;top;)pushdown(sta[top--]); 73 while(!isroot(x)){ 74 int y=fa[x],z=fa[y]; 75 if(!isroot(y)){ 76 if(c[z][0]==y^c[y][0]==x)rotate(x); 77 else rotate(y); 78 } 79 rotate(x); 80 } 81 } 82 void access(int x){ 83 for(int y=0;x;x=fa[x]){ 84 splay(x);c[x][1]=y;pushup(x);y=x; 85 } 86 } 87 void makeroot(int x){ 88 access(x);splay(x);rev[x]^=1; 89 } 90 int find(int x){ 91 access(x);splay(x); 92 while(c[x][0])x=c[x][0]; 93 return x; 94 } 95 void link(int x,int y){ 96 makeroot(x);fa[x]=y;splay(x); 97 } 98 void cut(int x,int y){ 99 makeroot(x);access(y);splay(y);c[y][0]=fa[x]=0; 100 } 101 void split(int x,int y){ 102 makeroot(x);access(y);splay(y); 103 } 104 int main(){ 105 //freopen("input.txt","r",stdin); 106 //freopen("output.txt","w",stdout); 107 n=read();m=read(); 108 for1(i,n-1){ 109 int x=read(),y=read(); 110 insert(x,y); 111 } 112 for1(i,n){ 113 s[i]=s[i]=v[i]=mul[i]=1;add[i]=0; 114 } 115 sta[++top]=1; 116 for1(i,top) 117 for(int k=sta[i],j=head[k];j;j=e[j].next){ 118 if(e[j].go!=fa[k]){ 119 fa[e[j].go]=k;sta[++top]=e[j].go; 120 } 121 } 122 for1(i,m){ 123 char ch=getchar(); 124 while(ch!='+'&&ch!='-'&&ch!='*'&&ch!='/')ch=getchar(); 125 switch(ch){ 126 case '-':{int u1=read(),v1=read(),u2=read(),v2=read();cut(u1,v1);link(u2,v2);break;} 127 case '+':{int u=read(),v=read(),c=read();split(u,v);update(v,c,1);break;} 128 case '*':{int u=read(),v=read(),c=read();split(u,v);update(v,0,c);break;} 129 case '/':{int u=read(),v=read();split(u,v);printf("%d\n",sum[v]);break;} 130 } 131 } 132 return 0; 133 }