前言:
一直听说树链剖分-树链剖分,现在见识一下,,,感觉不是很难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 }
来源:https://www.cnblogs.com/tak-fate/p/7190244.html