前言:
一直听说树链剖分-树链剖分,现在见识一下,,,感觉不是很难0.0
看了一下kuangbin模板基本秒懂
对于点,按重边优先给予每个点一个编号,对于一条重链上的点,编号则是连续的,将所有编号映射到线段树上,即可进行一切区间操作。
对于边的处理,我们将所有边对应到这条边节点更深的那个点上即可。
如果需要的操作只有求和,和单点更新/区间更新,直接用树状数组也是可以的,可能常数大那么一点点。
如果还需要更加强大的操作,显然用splay树维护也是可以的。。
比如树链上所有权值翻转等等。。不过,,这样差不多应该就快到LCT了。。虽然自己不会。。
不过过几天就该看了。
题意:
一棵树,每条边有一个权值,三种操作:
1、改变第i条边权值为v
2、将节点a到节点b之间的边权值取反
3、查询a到b之间最大的边权值
分析:
显然就是普通的树链剖分和线段树
但是要记得pushdown,
而对于lazy标记rev,当传下去的时候,不应该直接赋值为1或者0,而应该直接取反,用异或即可。
代码:
1 #include <math.h> 2 #include <stdio.h> 3 #include <stdlib.h> 4 #include <string.h> 5 #include <time.h> 6 #include <algorithm> 7 #include <iostream> 8 #include <map> 9 #include <queue> 10 #include <set> 11 #include <string> 12 #include <vector> 13 using namespace std; 14 15 const int maxn = 100010; 16 const int inf = 0x3f3f3f3f; 17 18 struct Edge { 19 int to, next; 20 } edge[maxn << 1]; 21 22 int head[maxn], tot; 23 int top[maxn]; 24 int fa[maxn]; 25 int deep[maxn]; 26 int num[maxn]; 27 int p[maxn]; 28 int fp[maxn]; 29 int son[maxn]; 30 int pos; 31 32 void init() { 33 tot = 0; 34 memset(head, -1, sizeof head); 35 pos = 0; 36 memset(son, -1, sizeof son); 37 } 38 39 void addedge(int u, int v) { 40 edge[tot].to = v; 41 edge[tot].next = head[u]; 42 head[u] = tot++; 43 } 44 void dfs1(int u, int pre, int d) { 45 deep[u] = d; 46 fa[u] = pre; 47 num[u] = 1; 48 for (int i = head[u]; i != -1; i = edge[i].next) { 49 int v = edge[i].to; 50 if (v != pre) { 51 dfs1(v, u, d + 1); 52 num[u] += num[v]; 53 if (son[u] == -1 || num[v] > num[son[u]]) son[u] = v; 54 } 55 } 56 } 57 58 void getpos(int u, int sp) { 59 top[u] = sp; 60 p[u] = pos++; 61 fp[p[u]] = u; 62 if (son[u] == -1) return; 63 getpos(son[u], sp); 64 for (int i = head[u]; i != -1; i = edge[i].next) { 65 int v = edge[i].to; 66 if (v != son[u] && v != fa[u]) getpos(v, v); 67 } 68 } 69 70 struct Node { 71 int left, right, maxs, mins; 72 int rev; 73 } node[maxn << 2]; 74 75 void build(int n, int left, int right) { 76 node[n].left = left; 77 node[n].right = right; 78 node[n].maxs = 0; 79 node[n].mins = 0; 80 node[n].rev = 0; 81 if (left == right) return; 82 int mid = (left + right) >> 1; 83 build(n << 1, left, mid); 84 build(n << 1 | 1, mid + 1, right); 85 } 86 87 void push_up(int n) { 88 node[n].maxs = max(node[n << 1].maxs, node[n << 1 | 1].maxs); 89 node[n].mins = min(node[n << 1].mins, node[n << 1 | 1].mins); 90 } 91 92 void push_down(int n) { 93 if (node[n].left == node[n].right) return; 94 if (node[n].rev) { 95 node[n << 1].rev ^= 1; 96 node[n << 1 | 1].rev ^= 1; 97 swap(node[n << 1].mins, node[n << 1].maxs); 98 node[n << 1].mins *= -1; 99 node[n << 1].maxs *= -1; 100 swap(node[n << 1 | 1].mins, node[n << 1 | 1].maxs); 101 node[n << 1 | 1].mins *= -1; 102 node[n << 1 | 1].maxs *= -1; 103 node[n].rev = 0; 104 } 105 } 106 107 void update(int n, int pos, int val) { 108 if (node[n].left == node[n].right) { 109 node[n].maxs = val; 110 node[n].mins = val; 111 node[n].rev = 0; 112 return; 113 } 114 push_down(n); 115 int mid = (node[n].left + node[n].right) >> 1; 116 if (pos <= mid) 117 update(n << 1, pos, val); 118 else 119 update(n << 1 | 1, pos, val); 120 push_up(n); 121 } 122 123 void Rev(int n, int left, int right) { 124 if (left <= node[n].left && node[n].right <= right) { 125 node[n].rev ^= 1; 126 swap(node[n].mins, node[n].maxs); 127 node[n].mins *= -1; 128 node[n].maxs *= -1; 129 return; 130 } 131 push_down(n); 132 int mid = (node[n].left + node[n].right) >> 1; 133 if (mid >= left) Rev(n << 1, left, right); 134 if (mid < right) Rev(n << 1 | 1, left, right); 135 push_up(n); 136 } 137 138 int query(int n, int left, int right) { 139 if (left <= node[n].left && node[n].right <= right) { 140 return node[n].maxs; 141 } 142 push_down(n); 143 int mid = (node[n].left + node[n].right) >> 1; 144 int maxs = -inf; 145 if (mid >= left) maxs = max(maxs, query(n << 1, left, right)); 146 if (mid < right) maxs = max(maxs, query(n << 1 | 1, left, right)); 147 push_up(n); 148 return maxs; 149 } 150 151 int findMax(int u, int v) { 152 int f1 = top[u], f2 = top[v]; 153 int tmp = -inf; 154 while (f1 != f2) { 155 if (deep[f1] < deep[f2]) { 156 swap(f1, f2); 157 swap(u, v); 158 } 159 tmp = max(tmp, query(1, p[f1], p[u])); 160 u = fa[f1]; 161 f1 = top[u]; 162 } 163 if (u == v) return tmp; 164 if (deep[u] > deep[v]) swap(u, v); 165 return max(tmp, query(1, p[son[u]], p[v])); 166 } 167 168 void Negate(int u, int v) { 169 int f1 = top[u], f2 = top[v]; 170 while (f1 != f2) { 171 if (deep[f1] < deep[f2]) { 172 swap(f1, f2); 173 swap(u, v); 174 } 175 Rev(1, p[f1], p[u]); 176 u = fa[f1]; 177 f1 = top[u]; 178 } 179 if (u == v) return; 180 if (deep[u] > deep[v]) swap(u, v); 181 Rev(1, p[son[u]], p[v]); 182 } 183 184 int e[maxn][3]; 185 186 int main() { 187 // freopen("1.out", "w", stdout); 188 int t; 189 int n; 190 scanf("%d", &t); 191 while (t--) { 192 init(); 193 scanf("%d", &n); 194 for (int i = 0; i < n - 1; i++) { 195 int u, v, c; 196 scanf("%d%d%d", &e[i][0], &e[i][1], &e[i][2]); 197 addedge(e[i][0], e[i][1]); 198 addedge(e[i][1], e[i][0]); 199 } 200 dfs1(1, 0, 0); 201 getpos(1, 1); 202 build(1, 0, pos - 1); 203 for (int i = 0; i < n - 1; i++) { 204 if (deep[e[i][0]] > deep[e[i][1]]) swap(e[i][0], e[i][1]); 205 update(1, p[e[i][1]], e[i][2]); 206 } 207 char op[10]; 208 int u, v; 209 while (scanf("%s", op)) { 210 if (op[0] == 'D') break; 211 scanf("%d%d", &u, &v); 212 if (op[0] == 'Q') 213 printf("%d\n", findMax(u, v)); 214 else if (op[0] == 'N') { 215 Negate(u, v); 216 } else { 217 update(1, p[e[u - 1][1]], v); 218 } 219 } 220 } 221 return 0; 222 }