【国家集训队】Tree II
Description
给定n个点的树,每个点有点权,维护如下操作:
- 将某一条链上的点的点权加或者乘一个数
- 将原有的一条边删除,加入一条新边,并保证操作完之后是一棵树
- 询问某一条链上所有点权之和
Solution
LCT维护
每一个点维护如下信息:父亲,儿子,点权,子树大小,子树的点权和,翻转标记,乘法标记,加法标记
这是一道LCT的模板题,难点在于处理三个标记的下放问题
根据运算优先级,乘法是要先算的,所以先放,放的时候子树的sum,乘法标记,加法标记,儿子的val统统都要乘一遍
放加法标记的时候,想到线段树的区间大小是稳定的,而Splay并不是,所以还要维护size,于是子树的sum要加上子树的size再乘上标记,而儿子的val和加法标记直接加上该标记的值
再注意一个小细节即可
Code
1 #include <bits/stdc++.h> 2 using namespace std; 3 typedef unsigned int ll; 4 const int mod = 51061; 5 const int N = 1e5 + 10; 6 inline int read() { 7 int ret = 0, op = 1; 8 char c = getchar(); 9 while (!isdigit(c)) { 10 if (c == '-') op = -1; 11 c = getchar(); 12 } 13 while (isdigit(c)) { 14 ret = ret * 10 + c - '0'; 15 c = getchar(); 16 } 17 return ret * op; 18 } 19 struct LCT { 20 int fa, ch[2], size; 21 ll val; 22 ll sum; 23 ll atag, mtag, tag; 24 } a[N]; 25 int n, m, s[N]; 26 inline void update(int now) { 27 a[now].size = a[a[now].ch[0]].size + a[a[now].ch[1]].size + 1; 28 a[now].sum = (a[a[now].ch[0]].sum + a[a[now].ch[1]].sum + a[now].val) % mod; 29 } 30 void add(ll &x, int y) { 31 x += y; 32 x %= mod; 33 } 34 void mul(ll &x, int y) { 35 x *= y; 36 x %= mod; 37 } 38 void rev(int now) { 39 swap(a[now].ch[0], a[now].ch[1]); 40 a[now].tag ^= 1; 41 } 42 void pushdown(int now) { 43 if (a[now].mtag != 1) { 44 mul(a[a[now].ch[0]].sum, a[now].mtag); mul(a[a[now].ch[0]].val, a[now].mtag); mul(a[a[now].ch[0]].mtag, a[now].mtag); mul(a[a[now].ch[0]].atag, a[now].mtag); 45 mul(a[a[now].ch[1]].sum, a[now].mtag); mul(a[a[now].ch[1]].val, a[now].mtag); mul(a[a[now].ch[1]].mtag, a[now].mtag); mul(a[a[now].ch[1]].atag, a[now].mtag); 46 a[now].mtag = 1; 47 } 48 if (a[now].atag) { 49 add(a[a[now].ch[0]].sum, a[now].atag * a[a[now].ch[0]].size); 50 add(a[a[now].ch[0]].val, a[now].atag); 51 add(a[a[now].ch[0]].atag, a[now].atag); 52 add(a[a[now].ch[1]].sum, a[now].atag * a[a[now].ch[1]].size); 53 add(a[a[now].ch[1]].val, a[now].atag); 54 add(a[a[now].ch[1]].atag, a[now].atag); 55 a[now].atag = 0; 56 } 57 if (a[now].tag) { 58 if (a[now].ch[0]) rev(a[now].ch[0]); 59 if (a[now].ch[1]) rev(a[now].ch[1]); 60 a[now].tag = 0; 61 } 62 } 63 inline int isnroot(int now) { 64 return a[a[now].fa].ch[0] == now || a[a[now].fa].ch[1] == now; 65 } 66 inline void rotate(int x) { 67 int y = a[x].fa; 68 int z = a[y].fa; 69 int xson = a[y].ch[1] == x; 70 int yson = a[z].ch[1] == y; 71 int B = a[x].ch[xson ^ 1]; 72 if (isnroot(y)) a[z].ch[yson] = x; a[x].ch[xson ^ 1] = y; a[y].ch[xson] = B; 73 if (B) a[B].fa = y; a[y].fa = x; a[x].fa = z; 74 update(y); 75 } 76 inline void splay(int x) { 77 int y = x, z = 0; 78 s[++z] = y; 79 while (isnroot(y)) y = a[y].fa, s[++z] = y; 80 while (z) pushdown(s[z--]); 81 while (isnroot(x)) { 82 y = a[x].fa; 83 z = a[y].fa; 84 if (isnroot(y)) 85 (a[z].ch[1] == y) ^ (a[y].ch[1] == x) ? rotate(x) : rotate(y); 86 rotate(x); 87 } 88 update(x); 89 } 90 void access(int x) { 91 for (register int y = 0; x; y = x, x = a[x].fa) { 92 splay(x); a[x].ch[1] = y; update(x); 93 } 94 } 95 void makeroot(int x) { 96 access(x); 97 splay(x); 98 rev(x); 99 } 100 void split(int x, int y) { 101 makeroot(x); 102 access(y); 103 splay(y); 104 } 105 void link(int x, int y) { 106 makeroot(x); 107 a[x].fa = y; 108 } 109 void cut(int x, int y) { 110 split(x, y); 111 a[x].fa = a[y].ch[0] = 0; 112 } 113 int main() { 114 n = read(); m = read(); 115 for (register int i = 1; i <= n; ++i) { 116 a[i].val = a[i].size = a[i].mtag = 1; 117 } 118 for (register int i = 1; i < n; ++i) { 119 int x = read(), y = read(); 120 link(x, y); 121 } 122 while (m--) { 123 char op = getchar(); 124 int x0, x1, x2; 125 if (op == '+') { 126 x0 = read(), x1 = read(), x2 = read(); 127 split(x0, x1); 128 add(a[x1].sum, x2 * a[x1].size); 129 add(a[x1].val, x2); 130 add(a[x1].atag, x2); 131 } 132 else if (op == '-') { 133 x0 = read(), x1 = read(); cut(x0, x1); 134 x0 = read(), x1 = read(); link(x0, x1); 135 } 136 else if (op == '*') { 137 x0 = read(), x1 = read(), x2 = read(); 138 split(x0, x1); 139 mul(a[x1].sum, x2); 140 mul(a[x1].val, x2); 141 mul(a[x1].mtag, x2); 142 mul(a[x1].atag, x2); 143 } 144 else { 145 x0 = read(), x1 = read(); 146 split(x0, x1); 147 printf("%d\n", a[x1].sum); 148 } 149 } 150 return 0; 151 }