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行,每行描述一个操作
 

Output

  对于每个/对应的答案输出一行
 

Sample Input

3 2
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

 
 
 
有加有乘,在平衡树上的操作和在线段树上的操作是一样的。。。
  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 }
View Code

 

posted @ 2016-05-22 16:38  HTWX  阅读(85)  评论(0编辑  收藏  举报