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
解题思路:
假如没有2操作,且图是树,是不是想起了线段树。
这道题也是一样的道理,LCT嘛,splay维护树链
代码:
1 // luogu-judger-enable-o2 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #define lll tr[spc].ch[0] 6 #define rrr tr[spc].ch[1] 7 #define ls ch[0] 8 #define rs ch[1] 9 typedef unsigned int lnt; 10 const lnt mod=51061; 11 struct trnt{ 12 int ch[2]; 13 int fa; 14 int lzt; 15 lnt add; 16 lnt mul; 17 lnt sum; 18 lnt wgt; 19 lnt val; 20 bool anc; 21 }tr[100005]; 22 int st[100001]; 23 int tp; 24 int n,q; 25 char cmd[10]; 26 int read() 27 { 28 int f=1,x=0; 29 char ss=getchar(); 30 while(ss<'0'||ss>'9'){if(ss=='-')f=-1;ss=getchar();} 31 while(ss>='0'&&ss<='9'){x=x*10+ss-'0';ss=getchar();} 32 return f*x; 33 } 34 int comd(void) 35 { 36 if(cmd[0]=='+') 37 return 1; 38 if(cmd[0]=='-') 39 return 2; 40 if(cmd[0]=='*') 41 return 3; 42 if(cmd[0]=='/') 43 return 4; 44 return 0; 45 } 46 bool whc(int spc) 47 { 48 return tr[tr[spc].fa].rs==spc; 49 } 50 void pushup(int spc) 51 { 52 tr[spc].wgt=tr[lll].wgt+tr[rrr].wgt+1; 53 tr[spc].sum=(tr[lll].sum+tr[rrr].sum+tr[spc].val)%mod; 54 } 55 void trr(int spc) 56 { 57 if(!spc) 58 return ; 59 tr[spc].lzt^=1; 60 std::swap(lll,rrr); 61 } 62 void Mul(int spc,lnt k) 63 { 64 if(!spc) 65 return ; 66 tr[spc].add=tr[spc].add*k%mod; 67 tr[spc].sum=tr[spc].sum*k%mod; 68 tr[spc].val=tr[spc].val*k%mod; 69 tr[spc].mul=tr[spc].mul*k%mod; 70 } 71 void Add(int spc,lnt k) 72 { 73 if(!spc) 74 return ; 75 if(tr[spc].mul) 76 { 77 Mul(lll,tr[spc].mul); 78 Mul(rrr,tr[spc].mul); 79 tr[spc].mul=1; 80 } 81 tr[spc].sum=(tr[spc].sum+tr[spc].wgt*k)%mod; 82 tr[spc].val=(tr[spc].val+k)%mod; 83 tr[spc].add=(tr[spc].add+k)%mod; 84 } 85 void pushdown(int spc) 86 { 87 if(tr[spc].lzt) 88 { 89 tr[spc].lzt=0; 90 trr(lll); 91 trr(rrr); 92 } 93 if(tr[spc].mul!=1) 94 { 95 Mul(lll,tr[spc].mul); 96 Mul(rrr,tr[spc].mul); 97 tr[spc].mul=1; 98 } 99 if(tr[spc].add) 100 { 101 Add(lll,tr[spc].add); 102 Add(rrr,tr[spc].add); 103 tr[spc].add=0; 104 } 105 } 106 void rotate(int spc) 107 { 108 int f=tr[spc].fa; 109 bool k=whc(spc); 110 tr[f].ch[k]=tr[spc].ch[!k]; 111 tr[spc].ch[!k]=f; 112 if(tr[f].anc) 113 { 114 tr[spc].anc=1; 115 tr[f].anc=0; 116 }else 117 tr[tr[f].fa].ch[whc(f)]=spc; 118 tr[spc].fa=tr[f].fa; 119 tr[f].fa=spc; 120 tr[tr[f].ch[k]].fa=f; 121 pushup(f); 122 pushup(spc); 123 } 124 void splay(int spc) 125 { 126 tp=0; 127 int x=spc; 128 while(!tr[x].anc) 129 st[++tp]=x,x=tr[x].fa; 130 st[++tp]=x; 131 while(tp) 132 pushdown(st[tp--]); 133 while(!tr[spc].anc) 134 { 135 int ft=tr[spc].fa; 136 if(tr[ft].anc) 137 { 138 rotate(spc); 139 return ; 140 } 141 if(whc(spc)^whc(ft)) 142 rotate(spc); 143 else 144 rotate(ft); 145 rotate(spc); 146 } 147 pushup(spc); 148 } 149 void access(int spc) 150 { 151 int lst=0; 152 while(spc) 153 { 154 splay(spc); 155 tr[rrr].anc=1; 156 tr[lst].anc=0; 157 rrr=lst; 158 pushup(spc); 159 lst=spc; 160 spc=tr[spc].fa; 161 } 162 } 163 void Mtr(int spc) 164 { 165 access(spc); 166 splay(spc); 167 trr(spc); 168 } 169 void split(int x,int y) 170 { 171 Mtr(x); 172 access(y); 173 splay(y); 174 } 175 void link(int x,int y) 176 { 177 Mtr(x); 178 tr[x].fa=y; 179 } 180 void cut(int x,int y) 181 { 182 split(x,y); 183 tr[y].ls=0; 184 tr[x].fa=0; 185 tr[x].anc=1; 186 pushup(y); 187 } 188 int main() 189 { 190 n=read(); 191 q=read(); 192 for(int i=1;i<=n;i++) 193 { 194 tr[i].anc=1; 195 tr[i].mul=1; 196 tr[i].val=1; 197 tr[i].wgt=tr[i].sum=1; 198 } 199 for(int i=1;i<n;i++) 200 { 201 int a=read(),b=read(); 202 link(a,b); 203 } 204 while(q--) 205 { 206 scanf("%s",cmd); 207 int opt=comd(); 208 if(opt==1) 209 { 210 int u=read(),v=read(),c=read(); 211 split(u,v); 212 Add(v,c); 213 } 214 if(opt==2) 215 { 216 int ua=read(),va=read(),ub=read(),vb=read(); 217 cut(ua,va); 218 link(ub,vb); 219 } 220 if(opt==3) 221 { 222 int u=read(),v=read(),c=read(); 223 split(u,v); 224 Mul(v,c); 225 } 226 if(opt==4) 227 { 228 int u=read(),v=read(); 229 split(u,v); 230 printf("%u ",tr[v].sum); 231 } 232 } 233 return 0; 234 }