题目大意
给一棵树,有两种操作,一种是改变某一条边的边权,一种是询问某两个结点间的路径的最大值
解题
具体思路参见2009年集训队漆子超的论文《分治算法在树的路径问题中的应用》
树链剖分裸题,无奈昨天一直TLE,非常怨念,今天重写了一发,居然A了,虽然也不快,3.89s
感觉我用的姿势应该是能看得下去的……
CODE
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 10010;
const int inf = 0x3fffffff;
int max(int a, int b) {
return a > b ? a : b;
}
struct edge {
int v, next;
edge() {}
edge(int a, int b) : v(a), next(b) {}
};
edge e[maxn*3];
struct data {
int x, y, d;
};
data E[maxn<<1];
int head[maxn], son[maxn], sz[maxn], pre[maxn], top[maxn], dep[maxn], hash[maxn];
int n, num, tot;
void add(int u, int v) {
e[tot] = edge(v, head[u]); head[u] = tot++;
e[tot] = edge(u, head[v]); head[v] = tot++;
}
void dfs(int u, int d) {
sz[u] = 1; son[u] = 0; dep[u] = d;
for (int i = head[u]; ~i; i = e[i].next) {
int v = e[i].v;
if (v == pre[u]) continue;
pre[v] = u;
dfs(v, d+1);
sz[u] += sz[v];
if (sz[v] > sz[son[u]]) son[u] = v;
}
}
void build_tree(int u, int fa) {
hash[u] = ++num; top[u] = fa;
if (son[u]) build_tree(son[u], top[u]);
for (int i = head[u]; ~i; i = e[i].next) {
int v = e[i].v;
if (v == pre[u] || v == son[u]) continue;
build_tree(v, v);
}
}
#define lson l, m, rt<<1
#define rson m+1, r, rt<<1|1
int mx[maxn<<2];
void PushUp(int rt) {
mx[rt] = max(mx[rt<<1], mx[rt<<1|1]);
}
void build(int l, int r, int rt) {
mx[rt] = -inf;
if (l == r) return;
int m = (l+r) >> 1;
build(lson); build(rson);
}
void update(int pos, int x, int l, int r, int rt) {
if (l == r) {
mx[rt] = x;
return;
}
int m = (l+r) >> 1;
if (pos <= m) update(pos, x, lson);
else update(pos, x, rson);
PushUp(rt);
}
int query(int ll, int rr, int l, int r, int rt) {
if (ll <= l && rr >= r) return mx[rt];
int m = (l+r) >> 1;
int res = -inf;
if (ll <= m) res = max(res, query(ll, rr, lson));
if (rr > m) res = max(res, query(ll, rr, rson));
return res;
}
int Query(int x, int y) {
int ans = -inf;
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
ans = max(ans, query(hash[top[x]], hash[x], 2, n, 1));
x = pre[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
if (x != y)
ans = max(ans, query(hash[x]+1, hash[y], 2, n, 1));
return ans;
}
void solve() {
scanf("%d", &n);
memset(head, -1, sizeof(head));
tot = 0;
for (int i = 1; i < n; i++) {
scanf("%d%d%d", &E[i].x, &E[i].y, &E[i].d);
add(E[i].x, E[i].y);
}
sz[0] = 0; num = 0;
dfs(1, 1);
build_tree(1, 1);
build(2, n, 1);
for (int i = 1; i < n; i++) {
if (dep[E[i].x] < dep[E[i].y]) swap(E[i].x, E[i].y);
update(hash[E[i].x], E[i].d, 2, n, 1);
}
char op[10];
while (1) {
scanf("%s", op);
if (op[0] == 'D') break;
int x, y;
scanf("%d%d", &x, &y);
if (op[0] == 'C') update(hash[E[x].x], y, 2, n, 1);
else if (op[0] == 'Q') printf("%d\n", Query(x, y));
}
}
int main() {
int cs; scanf("%d", &cs);
while (cs--) solve();
return 0;
}