bzoj2631 tree LCT 区间修改,求和
tree
Time Limit: 30 Sec Memory Limit: 128 MBSubmit: 4962 Solved: 1697
[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
题解:
基本操作,可以作为模板题
1 #include<cstring> 2 #include<cmath> 3 #include<algorithm> 4 #include<iostream> 5 #include<cstdio> 6 7 #define N 100007 8 #define ll unsigned int 9 using namespace std; 10 const int mod=51061; 11 inline int read() 12 { 13 int x=0,f=1;char ch=getchar(); 14 while(ch>'9'||ch<'0'){if (ch=='-') f=-1;ch=getchar();} 15 while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} 16 return x*f; 17 } 18 19 int n,q; 20 ll sum[N],num[N],add[N],mul[N],rev[N],siz[N]; 21 int c[N][2],fa[N],st[N]; 22 23 void change(int p,ll mu,ll ad) 24 { 25 if (!p) return; 26 mul[p]=mul[p]*mu%mod; 27 add[p]=(add[p]*mu+ad)%mod; 28 num[p]=(num[p]*mu+ad)%mod; 29 sum[p]=(sum[p]*mu+ad*siz[p])%mod; 30 } 31 void update(int p) 32 { 33 int l=c[p][0],r=c[p][1]; 34 siz[p]=(siz[l]+siz[r]+1)%mod; 35 sum[p]=(sum[l]+sum[r]+num[p])%mod; 36 } 37 void pushdown(int p) 38 { 39 int l=c[p][0],r=c[p][1]; 40 if (rev[p]) 41 { 42 rev[p]^=1,rev[l]^=1,rev[r]^=1; 43 swap(c[p][0],c[p][1]); 44 } 45 if (add[p]!=0||mul[p]!=1) 46 { 47 change(l,mul[p],add[p]); 48 change(r,mul[p],add[p]); 49 } 50 add[p]=0,mul[p]=1; 51 } 52 inline bool isroot(int x) 53 { 54 return c[fa[x]][0]!=x&&c[fa[x]][1]!=x; 55 } 56 void rotate(int x) 57 { 58 int y=fa[x],z=fa[y],l,r; 59 if (c[y][0]==x) l=0;else l=1;r=l^1; 60 if (!isroot(y)) 61 { 62 if (c[z][0]==y) c[z][0]=x; 63 else c[z][1]=x; 64 } 65 fa[x]=z,fa[y]=x,fa[c[x][r]]=y; 66 c[y][l]=c[x][r],c[x][r]=y; 67 update(y),update(x); 68 } 69 void splay(int x) 70 { 71 int top=0;st[++top]=x; 72 for (int i=x;!isroot(i);i=fa[i]) 73 st[++top]=fa[i]; 74 for (int i=top;i>=1;i--) 75 pushdown(st[i]); 76 while(!isroot(x)) 77 { 78 int y=fa[x],z=fa[y]; 79 if (!isroot(y)) 80 { 81 if (c[y][0]==x^c[z][0]==y) rotate(x); 82 else rotate(y); 83 } 84 rotate(x); 85 } 86 } 87 void access(int x) 88 { 89 int t=0; 90 while(x) 91 { 92 splay(x); 93 c[x][1]=t; 94 update(x); 95 t=x,x=fa[x]; 96 } 97 } 98 void makeroot(int x) 99 { 100 access(x); 101 splay(x); 102 rev[x]^=1; 103 } 104 void link(int x,int y) 105 { 106 makeroot(x); 107 fa[x]=y; 108 splay(x); 109 } 110 void cut(int x,int y) 111 { 112 makeroot(x); 113 access(y); 114 splay(y); 115 fa[x]=c[y][0]=0; 116 } 117 int main() 118 { 119 // freopen("fzy.in","r",stdin); 120 // freopen("fzy.out","w",stdout); 121 122 n=read(),q=read(); 123 for (int i=1;i<=n;i++)num[i]=sum[i]=mul[i]=siz[i]=1; 124 for (int i=1;i<n;i++) 125 { 126 int u=read(),v=read(); 127 link(u,v); 128 } 129 for (int i=1;i<=q;i++) 130 { 131 char ch[2]; 132 scanf("%s",ch); 133 switch(ch[0]) 134 { 135 case'+': 136 { 137 int u=read(),v=read();ll c=read(); 138 makeroot(u),access(v),splay(v); 139 change(v,1,c);break; 140 } 141 case'-': 142 { 143 int u1=read(),v1=read(),u2=read(),v2=read(); 144 cut(u1,v1),link(u2,v2);break; 145 } 146 case'*': 147 { 148 int u=read(),v=read();ll c=read(); 149 makeroot(u),access(v),splay(v); 150 change(v,c,0);break; 151 } 152 case'/': 153 { 154 int u=read(),v=read(); 155 makeroot(u); 156 access(v); 157 splay(v); 158 printf("%d\n",sum[v]); 159 break; 160 } 161 } 162 } 163 }