线段树是按照 扶苏的问题 那题写的,然后错了,感觉树剖部分没错,贴代码:
#include <iostream>
#define maxn 1000000001
using namespace std;
int n, k, cnt;
//基础树上需求
int fa[100005], dep[100005];
//树剖需求
int sz[100005], top[100005], wson[100005];
//树剖线段树需求
int num[100005], val[100005];
//线段树需求
int ma[400005], tag[400005], cov[400005];
//前向星需求
int pre[100005];
struct Node {int from, to, len, next;}a[200005];
void add (int x, int y, int z) {
a[++ k] = {x, y, z, pre[x]};
pre[x] = k;
}
//树剖 dfs
void dfs1 (int x) {
for (int i = pre[x]; i; i = a[i].next) {
int v = a[i].to;
if (v == fa[x]) continue;
dep[v] = dep[x] + 1;
fa[v] = x;
dfs1 (v);
if (sz[v] > sz[wson[x] ]) wson[x] = v;
}
sz[fa[x] ] += ++ sz[x];
}
void dfs2 (int x, int t) {
top[x] = t;
num[x] = ++ cnt;
if (wson[x]) dfs2 (wson[x], t);
for (int i = pre[x]; i; i = a[i].next) {
int v = a[i].to;
if (v == fa[x] || v == wson[x]) continue;
dfs2 (v, v);
}
}
//线段树
void pushdown (int l, int r, int k) {
if (cov[k] != maxn) {
cov[k << 1] = cov[k << 1 | 1] = cov[k];
ma[k << 1] = ma[k << 1 | 1] = cov[k];
} else if (tag[k]) {
if (cov[k << 1] != maxn) cov[k << 1] += tag[k];
else tag[k << 1] += tag[k];
if (cov[k << 1 | 1] != maxn) cov[k << 1 | 1] += tag[k];
else tag[k << 1 | 1] += tag[k];
}
cov[k] = maxn;
tag[k] = 0;
}
void build (int l, int r, int k) {
cov[k] = maxn;
if (l == r) {
ma[k] = val[l];
return;
}
int mid = l + r >> 1;
build (l, mid, k << 1);
build (mid + 1, r, k << 1 | 1);
ma[k] = max (ma[k << 1], ma[k << 1 | 1]);
}
void upd (int l, int r, int k, int x, int y) {
if (l == r) {
tag[k] = 0;
cov[k] = maxn;
ma[k] = y;
return;
}
int mid = l + r >> 1;
if (x <= mid) upd (l, mid, k << 1, x, y);
else upd (mid + 1, r, k << 1 | 1, x, y);
ma[k] = max (ma[k << 1], ma[k << 1 | 1]);
}
void update (int f, int l, int r, int k, int x, int y, int z) {
if (x <= l && y >= r) {
if (f == 1) {
tag[k] = 0;
cov[k] = z;
ma[k] = z;
} else {
if (cov[k] != maxn) cov[k] += z;
else tag[k] += z;
ma[k] += z;
}
return;
}
pushdown (l, r, k);
int mid = l + r >> 1;
if (x <= mid) update (f, l, mid, k << 1, x, y, z);
if (y > mid) update (f, mid + 1, r, k << 1 | 1, x, y, z);
ma[k] = max (ma[k << 1], ma[k << 1 | 1]);
}
int query (int l, int r, int k, int x, int y) {
if (x <= l && y >= r) return ma[k];
int mid = l + r >> 1, res = 0;
pushdown (l, r, k);
if (x <= mid) res = query (l, mid, k << 1, x, y);
if (y > mid) res = max (res, query (mid + 1, r, k << 1 | 1, x, y) );
return res;
}
//树链剖分
void Upd (int x, int y, int z, int f) {
while (top[x] != top[y]) {
if (dep[top[x] ] < dep[top[y] ]) swap (x, y);
update (f, 1, n, 1, num[top[x] ], num[x], z);
x = fa[top[x] ];
}
if (x == y) return;
if (dep[x] > dep[y]) swap (x, y);
update (f, 1, n, 1, num[x] + 1, num[y], z);
}
int q (int x, int y) {
int ret = 0;
while (top[x] != top[y]) {
if (dep[top[x] ] < dep[top[y] ]) swap (x, y);
ret = max (ret, query (1, n, 1, num[top[x] ], num[x]) );
x = fa[top[x] ];
}
if (x == y) return ret;
if (dep[x] > dep[y]) swap (x, y);
return max (ret, query (1, n, 1, num[x] + 1, num[y]) );
}
int main () {
dep[1] = 1;
scanf ("%d", &n);
for (int i = 1; i < n; i ++) {
int u, v, w;
scanf ("%d%d%d", &u, &v, &w);
add (u, v, w);
add (v, u, w);
}
dfs1 (1);
dfs2 (1, 1);
for (int i = 1; i < n; i ++) {
int u = a[2 * i].from, v = a[2 * i].to, w = a[2 * i].len;
if (fa[v] == u) swap (u, v);
val[num[u] ] = w;
}
build (1, n, 1);
char s[20];
int x, y, z;
while (1) {
scanf ("%s", s);
if (s[0] == 'S') break;
scanf ("%d%d", &x, &y);
if (s[0] == 'C' && s[1] == 'h') {
int u = a[2 * x].from, v = a[2 * x].to;
if (fa[v] == u) swap (u, v);
upd (1, n, 1, num[u], y);
continue;
}
if (s[0] != 'M') scanf ("%d", &z);
if (s[0] == 'C') Upd (x, y, z, 1);
else if (s[0] == 'A') Upd (x, y, z, 2);
else cout << q (x, y) << "\n";
}
return 0;
}