[国家集训队2012]tree(伍一鸣)
tree(伍一鸣)
时间限制:2.5s 内存限制:64.0M
【问题描述】
一棵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的余数。
+ 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的余数。
【输入格式】
第一行两个整数n,q
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作
接下来n-1行每行两个正整数u,v,描述这棵树
接下来q行,每行描述一个操作
【输出格式】
对于每个/对应的答案输出一行
【样例输入】
3 2
1 2
2 3
* 1 3 4
/ 1 1
1 2
2 3
* 1 3 4
/ 1 1
【样例输出】
4
【数据规模和约定】
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
另外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<bits/stdc++.h> 2 #define ll long long 3 using namespace std; 4 const int mod=51061; 5 const int inf=1e5+5; 6 int n,q,tot,fi[inf],to[inf<<1],next[inf<<1]; 7 int ch[inf][2],fa[inf],rev[inf],siz[inf]; 8 ll add[inf],mul[inf],sum[inf],v[inf]; 9 void edge_add(int x,int y){ 10 to[++tot]=y; 11 next[tot]=fi[x]; 12 fi[x]=tot; 13 } 14 void dfs(int x,int f){ 15 fa[x]=f; 16 siz[x]=1; 17 v[x]=1; 18 mul[x]=1; 19 add[x]=0; 20 sum[x]=1; 21 for(int i=fi[x];i;i=next[i]) 22 if(to[i]!=f)dfs(to[i],x); 23 } 24 bool get(int x){ 25 return ch[fa[x]][1]==x; 26 } 27 bool isroot(int x){ 28 return ch[fa[x]][1]!=x&&ch[fa[x]][0]!=x; 29 } 30 void update(int x){ 31 int ls=ch[x][0],rs=ch[x][1]; 32 siz[x]=siz[ls]+siz[rs]+1; 33 sum[x]=(sum[ls]+sum[rs]+v[x])%mod; 34 } 35 void pushdown(int x){ 36 int ls=ch[x][0],rs=ch[x][1]; 37 if(rev[x]){ 38 rev[x]=0; 39 rev[ls]^=1; 40 rev[rs]^=1; 41 swap(ch[ls][0],ch[ls][1]); 42 swap(ch[rs][0],ch[rs][1]); 43 } 44 v[x]=(v[x]*mul[x]+add[x])%mod; 45 mul[ls]=mul[ls]*mul[x]%mod; 46 mul[rs]=mul[rs]*mul[x]%mod; 47 add[ls]=(mul[x]*add[ls]+add[x])%mod; 48 add[rs]=(mul[x]*add[rs]+add[x])%mod; 49 sum[ls]=(sum[ls]*mul[x]+add[x]*siz[ls])%mod; 50 sum[rs]=(sum[rs]*mul[x]+add[x]*siz[rs])%mod; 51 add[x]=0;mul[x]=1; 52 } 53 void zig(int x){ 54 int old=fa[x],oldf=fa[old]; 55 pushdown(old); 56 pushdown(x); 57 bool p=get(x); 58 if(!isroot(old))ch[oldf][get(old)]=x; 59 fa[x]=oldf; 60 fa[ch[old][p]=ch[x][p^1]]=old; 61 fa[ch[x][p^1]=old]=x; 62 update(old); 63 update(x); 64 } 65 void splay(int x){ 66 for(;!isroot(x);zig(x)) 67 if(!isroot(fa[x]))zig(get(x)==get(fa[x])?fa[x]:x); 68 pushdown(x);//防止单独一个点成splay标记未下传 69 } 70 void access(int x){ 71 int last=0; 72 while(x){ 73 splay(x); 74 ch[x][1]=last; 75 update(x); 76 last=x; 77 x=fa[x]; 78 } 79 } 80 void makeroot(int x){ 81 access(x); 82 splay(x); 83 rev[x]^=1; 84 swap(ch[x][0],ch[x][1]); 85 } 86 void cut(int x,int y){ 87 makeroot(x); 88 access(y); 89 splay(y); 90 ch[y][0]=fa[x]=0; 91 update(y); 92 } 93 void link(int x,int y){ 94 makeroot(x); 95 fa[x]=y; 96 } 97 void Add(int x,int y,int z){ 98 makeroot(x); 99 access(y); 100 splay(y); 101 add[y]=(add[y]+z)%mod; 102 sum[y]=(sum[y]+z*siz[y])%mod; 103 } 104 void Mul(int x,int y,int z){ 105 makeroot(x); 106 access(y); 107 splay(y); 108 add[y]=add[y]*z%mod; 109 mul[y]=mul[y]*z%mod; 110 sum[y]=sum[y]*z%mod; 111 } 112 int Q(int x,int y){ 113 makeroot(x); 114 access(y); 115 splay(y); 116 return sum[y]; 117 } 118 int main() 119 { 120 scanf("%d%d",&n,&q); 121 for(int i=1;i<n;i++){ 122 int x,y; 123 scanf("%d%d",&x,&y); 124 edge_add(x,y);edge_add(y,x); 125 } 126 dfs(1,0); 127 for(int i=1;i<=q;i++){ 128 char c; 129 cin>>c; 130 if(c==‘+‘){ 131 int u,v,c; 132 scanf("%d%d%d",&u,&v,&c); 133 Add(u,v,c); 134 } 135 else if(c==‘-‘){ 136 int u1,v1,u2,v2; 137 scanf("%d%d%d%d",&u1,&v1,&u2,&v2); 138 cut(u1,v1); 139 link(u2,v2); 140 } 141 else if(c==‘*‘){ 142 int u,v,c; 143 scanf("%d%d%d",&u,&v,&c); 144 Mul(u,v,c); 145 } 146 else if(c==‘/‘){ 147 int x,y; 148 scanf("%d%d",&x,&y); 149 printf("%d\n",Q(x,y)); 150 } 151 } 152 return 0; 153 }