別的不說,先%爲敬%%%%%%%%%ide
寫個LCA,跑的比HKjournalistTarjan還快,把倍增吊起來打......ui
反正就是那樣,重兒子是爲了保證時間複雜度。spa
DFS_1要求出d,fa,son,sizcode
DFS_2要求出top,id(剖出來的下標)blog
基本思路是靠着top最多會通過log次,不斷跳topio
重鏈剖出來是連續的,能夠區間操做。event
樹剖求LCA:模板
1 #include <cstdio> 2 3 const int N = 500010; 4 5 struct Edge { 6 int v, nex; 7 }edge[N << 1]; int t; 8 int e[N], A[N], root, num; 9 int top[N], son[N], fa[N], siz[N], id[N], d[N]; 10 11 inline void add(int x, int y) { 12 t++; 13 edge[t].v = y; 14 edge[t].nex = e[x]; 15 e[x] = t; 16 return; 17 } 18 19 void DFS_1(int x, int deep, int f) { 20 d[x] = deep; 21 siz[x] = 1; 22 fa[x] = f; 23 for(int i = e[x]; i; i = edge[i].nex) { 24 int y = edge[i].v; 25 if(y == f) { 26 continue; 27 } 28 DFS_1(y, deep + 1, x); 29 siz[x] += siz[y]; 30 if(siz[y] > siz[son[x]]) { 31 son[x] = y; 32 } 33 } 34 return; 35 } 36 37 void DFS_2(int x, int k) { 38 top[x] = k; 39 id[x] = ++num; 40 A[num] = x; 41 if(son[x]) { 42 DFS_2(son[x], k); 43 } 44 for(int i = e[x]; i; i = edge[i].nex) { 45 int y = edge[i].v; 46 if(y == son[x] || y == fa[x]) { 47 continue; 48 } 49 DFS_2(y, y); 50 } 51 return; 52 } 53 54 inline int lca(int x, int y) { 55 while(top[x] != top[y]) { 56 if(d[top[x]] > d[top[y]]) { 57 x = fa[top[x]]; 58 } 59 else { 60 y = fa[top[y]]; 61 } 62 } 63 return d[x] > d[y] ? y : x; 64 } 65 66 int main() { 67 int n, m; 68 scanf("%d%d%d", &n, &m, &root); 69 int x, y; 70 for(int i = 1; i < n; i++) { 71 scanf("%d%d", &x, &y); 72 add(x, y); 73 add(y, x); 74 } 75 DFS_1(root, 1, 0); 76 DFS_2(root, root); 77 while(m--) { 78 scanf("%d%d", &x, &y); 79 printf("%d\n", lca(x, y)); 80 } 81 return 0; 82 }
接下來是水題狂練,狂K水題,水門專題......class
HAOI2015 樹上操做cli
省選出樹剖模板還行。
1 #include <cstdio> 2 typedef long long LL; 3 const int N = 100010; 4 5 struct Edge { 6 int v, nex; 7 }edge[N << 1]; int t; 8 int e[N], A[N], root, num; 9 int d[N], fa[N], top[N], son[N], id[N], siz[N]; 10 11 int n; 12 LL sum[N << 2], tag[N << 2], val[N]; 13 14 inline void add(int x, int y) { 15 t++; 16 edge[t].v = y; 17 edge[t].nex = e[x]; 18 e[x] = t; 19 return; 20 } 21 22 void DFS_1(int x, int deep, int f) { 23 fa[x] = f; 24 siz[x] = 1; 25 d[x] = deep; 26 for(int i = e[x]; i; i = edge[i].nex) { 27 int y = edge[i].v; 28 if(y == f) { 29 continue; 30 } 31 DFS_1(y, deep + 1, x); 32 siz[x] += siz[y]; 33 if(siz[y] > siz[son[x]]) { 34 son[x] = y; 35 } 36 } 37 return; 38 } 39 40 void DFS_2(int x, int k) { 41 top[x] = k; 42 id[x] = ++num; 43 A[num] = x; 44 if(son[x]) { 45 DFS_2(son[x], k); 46 } 47 for(int i = e[x]; i; i = edge[i].nex) { 48 int y = edge[i].v; 49 if(y == fa[x] || y == son[x]) { 50 continue; 51 } 52 DFS_2(y, y); 53 } 54 return; 55 } 56 57 inline void pushup(int l, int r, int o) { 58 if(l == r) { 59 return; 60 } 61 sum[o] = sum[o << 1] + sum[o << 1 | 1]; 62 return; 63 } 64 65 inline void pushdown(int l, int r, int o) { 66 if(l == r) { 67 tag[o] = 0; 68 return; 69 } 70 if(!tag[o]) { 71 return; 72 } 73 int mid = (l + r) >> 1; 74 int ls = o << 1; 75 int rs = ls | 1; 76 LL k = tag[o]; 77 78 tag[ls] += k; 79 tag[rs] += k; 80 sum[ls] += k * (mid - l + 1); 81 sum[rs] += k * (r - mid); 82 83 tag[o] = 0; 84 return; 85 } 86 87 inline void build(int l, int r, int o) { 88 if(l == r) { 89 sum[o] = val[A[r]]; 90 return; 91 } 92 int mid = (l + r) >> 1; 93 build(l, mid, o << 1); 94 build(mid + 1, r, o << 1 | 1); 95 pushup(l, r, o); 96 return; 97 } 98 99 inline void add(int L, int R, LL v, int l, int r, int o) { 100 if(L <= l && r <= R) { 101 tag[o] += v; 102 sum[o] += v * (r - l + 1); 103 return; 104 } 105 pushdown(l, r, o); 106 int mid = (l + r) >> 1; 107 if(L <= mid) { 108 add(L, R, v, l, mid, o << 1); 109 } 110 if(mid < R) { 111 add(L, R, v, mid + 1, r, o << 1 | 1); 112 } 113 pushup(l, r, o); 114 return; 115 } 116 117 inline LL ask(int L, int R, int l, int r, int o) { 118 if(L <= l && r <= R) { 119 return sum[o]; 120 } 121 if(r < L || R < l) { 122 return 0; 123 } 124 pushdown(l, r, o); 125 int mid = (l + r) >> 1; 126 return ask(L, R, l, mid, o << 1) + ask(L, R, mid + 1, r, o << 1 | 1); 127 } 128 129 inline LL ask(int x) { 130 LL ans = 0; 131 while(top[x] != root) { 132 ans += ask(id[top[x]], id[x], 1, n, 1); 133 x = fa[top[x]]; 134 } 135 ans += ask(id[root], id[x], 1, n, 1); 136 return ans; 137 } 138 139 int main() { 140 int m; 141 scanf("%d%d", &n, &m); 142 for(int i = 1; i <= n; i++) { 143 scanf("%lld", &val[i]); 144 } 145 root = 1; 146 int x, f; 147 LL y; 148 for(int i = 1; i < n; i++) { 149 scanf("%d%d", &x, &y); 150 add(x, y); 151 add(y, x); 152 } 153 DFS_1(root, 1, 0); 154 DFS_2(root, root); 155 build(1, n, 1); 156 while(m--) { 157 scanf("%d", &f); 158 if(f == 1) { 159 scanf("%d%lld", &x, &y); 160 add(id[x], id[x], y, 1, n, 1); 161 } 162 else if(f == 2) { 163 scanf("%d%lld", &x, &y); 164 add(id[x], id[x] + siz[x] - 1, y, 1, n, 1); 165 } 166 else { 167 scanf("%d", &x); 168 printf("%lld\n", ask(x)); 169 } 170 } 171 return 0; 172 }
洛谷 P3950 部落衝突
仔細思考發現這TM不就是樹剖裸題嗎?
若是刪邊就邊權爲1,加邊則爲0,聯通條件是鏈權爲0
1 #include <cstdio> 2 3 const int N = 300010; 4 5 struct Edge { 6 int v, nex; 7 }edge[N << 1]; int t; 8 int e[N], d[N], siz[N], son[N], fa[N], id[N], top[N]; 9 int num, A[N], B[N], sum[N << 2], n; 10 11 inline void add(int x, int y) { 12 t++; 13 edge[t].v = y; 14 edge[t].nex = e[x]; 15 e[x] = t; 16 return; 17 } 18 19 void DFS_1(int x, int deep, int f) { 20 siz[x] = 1; 21 fa[x] = f; 22 d[x] = deep; 23 for(int i = e[x]; i; i = edge[i].nex) { 24 int y = edge[i].v; 25 if(y == f) { 26 continue; 27 } 28 DFS_1(y, deep + 1, x); 29 siz[x] += siz[y]; 30 if(siz[y] > siz[son[x]]) { 31 son[x] = y; 32 } 33 } 34 return; 35 } 36 37 void DFS_2(int x, int k) { 38 top[x] = k; 39 id[x] = ++num; 40 A[num] = x; 41 if(son[x]) { 42 DFS_2(son[x], k); 43 } 44 for(int i = e[x]; i; i = edge[i].nex) { 45 int y = edge[i].v; 46 if(y == fa[x] || y == son[x]) { 47 continue; 48 } 49 DFS_2(y, y); 50 } 51 return; 52 } 53 54 inline void pushup(int l, int r, int o) { 55 if(l == r) { 56 return; 57 } 58 sum[o] = sum[o << 1] + sum[o << 1 | 1]; 59 return; 60 } 61 62 void build(int l, int r, int o) { 63 if(l == r) { 64 sum[o] = 0; 65 return; 66 } 67 int mid = (l + r) >> 1; 68 build(l, mid, o << 1); 69 build(mid + 1, r, o << 1 | 1); 70 pushup(l, r, o); 71 return; 72 } 73 74 int ask(int L, int R, int l, int r, int o) { 75 if(L <= l && r <= R) { 76 return sum[o]; 77 } 78 if(r < L || R < l) { 79 return 0; 80 } 81 int mid = (l + r) >> 1; 82 return ask(L, R, l, mid, o << 1) + ask(L, R, mid + 1, r, o << 1 | 1); 83 } 84 85 void change(int p, int a, int l, int r, int o) { 86 if(l == r) { 87 sum[o] = a; 88 return; 89 } 90 int mid = (l + r) >> 1; 91 if(p <= mid) { 92 change(p, a, l, mid, o << 1); 93 } 94 else { 95 change(p, a, mid + 1, r, o << 1 | 1); 96 } 97 pushup(l, r, o); 98 return; 99 } 100 101 inline int ask(int x) { 102 int ans = 0; 103 while(x) { 104 ans += ask(id[top[x]], id[x], 1, n, 1); 105 x = fa[top[x]]; 106 } 107 return ans; 108 } 109 110 inline int lca(int x, int y) { 111 while(top[x] != top[y]) { 112 if(d[top[x]] > d[top[y]]) { 113 x = fa[top[x]]; 114 } 115 else { 116 y = fa[top[y]]; 117 } 118 } 119 return d[x] > d[y] ? y : x; 120 } 121 122 int main() { 123 int m, x, y; 124 char c[20]; 125 scanf("%d%d", &n, &m); 126 for(int i = 1; i < n; i++) { 127 scanf("%d%d", &x, &y); 128 add(x, y); 129 add(y, x); 130 } 131 DFS_1(1, 1, 0); 132 DFS_2(1, 1); 133 build(1, n, 1); 134 num = 0; 135 for(int i = 1; i <= m; i++) { 136 scanf("%s", c); 137 scanf("%d", &x); 138 if(c[0] == 'Q') { 139 scanf("%d", &y); 140 int t = ask(x) + ask(y) - (ask(lca(x, y)) << 1); 141 if(t) { 142 printf("No\n"); 143 } 144 else { 145 printf("Yes\n"); 146 } 147 } 148 else if(c[0] == 'C') { 149 scanf("%d", &y); 150 A[++num] = x; 151 B[num] = y; 152 if(fa[y] == x) { 153 x = y; 154 } 155 change(id[x], 1, 1, n, 1); 156 } 157 else { 158 y = A[x]; 159 x = B[x]; 160 if(fa[y] == x) { 161 x = y; 162 } 163 change(id[x], 0, 1, n, 1); 164 } 165 } 166 return 0; 167 }