[spoj QTREE Query on a tree]树链剖分
题目链接:[spoj QTREE Query on a tree]
题意描述:给定一棵顶点数为N的带权树。有Q次操作,每次操作或者改变第
i
条边的权值,或者查询顶点
解题思路:
树链剖分的入门题。今天比较系统的学习了一下树链剖分。其实树链剖分就是将树上的边(点)映射到若干条连续的线段上。然后结合一下线段树等数据结构,就可以在
比较关键的就是如何将树上的边(点)映射到若干条连续的线段上。——求出所有的重链,然后每条重链就构成了一条线段。
树剖原理请参考:ACdreamers 的 《树链剖分原理》
#include <bits/stdc++.h>
using namespace std;
#define FIN freopen("input.txt", "r", stdin)
#define lson l, mid, (rt << 1)
#define rson mid + 1, r, (rt << 1 | 1)
#define __mid__ int mid = (l + r) >> 1
typedef long long LL;
const int MAXN = 10000 + 5;
int T, N;
struct Edge {
int v, next;
Edge() {}
Edge(int v, int next) : v(v), next(next) {}
} edge[MAXN << 1];
int head[MAXN], ESZ, E[MAXN][3];
int siz[MAXN], top[MAXN], fa[MAXN], son[MAXN], dep[MAXN], tid[MAXN], rk[MAXN], id;
int seg[MAXN * 3];
void init() {
ESZ = 0;
id = 0;
memset(head, -1, sizeof(head));
memset(son, -1, sizeof(son));
}
void add_edge(int u, int v) {
edge[ESZ] = Edge(v, head[u]);
head[u] = ESZ ++;
}
void dfs1(int u, int pre, int k) {
int v;
siz[u] = 1;
fa[u] = pre;
dep[u] = k;
for(int i = head[u]; ~i; i = edge[i].next) {
v = edge[i].v;
if(v == pre) continue;
dfs1(v, u, k + 1);
siz[u] += siz[v];
if(son[u] == -1 || siz[son[u]] < siz[v]) son[u] = v;
}
}
void dfs2(int u, int tp) {
int v;
tid[u] = ++ id;
rk[tid[u]] = u;
top[u] = tp;
if(son[u] == -1) return;
dfs2(son[u], tp);
for(int i = head[u]; ~i; i = edge[i].next) {
v = edge[i].v;
if(v == fa[u] || v == son[u]) continue;
dfs2(v, v);
}
}
inline void pushUp(const int& rt) {
seg[rt] = max(seg[rt << 1], seg[rt << 1 | 1]);
}
void update(const int& p, const int& v, int l, int r, int rt) {
if(l == r) {
seg[rt] = v;
return;
}
__mid__;
if(p <= mid) update(p, v, lson);
else update(p, v, rson);
pushUp(rt);
}
int query(const int& L, const int& R, int l, int r, int rt) {
if(L <= l && r <= R) {
return seg[rt];
}
__mid__;
int ret = 0;
if(L <= mid) ret = query(L, R, lson);
if(R > mid) ret = max(ret, query(L, R, rson));
return ret;
}
int getAns(int u, int v) {
int ret = 0, f1 = top[u], f2 = top[v];
while(f1 != f2) {
if(dep[f1] < dep[f2]) {
swap(u, v);
swap(f1, f2);
}
ret = max(ret, query(tid[f1], tid[u], 1, id, 1));
u = fa[f1], f1 = top[u];
}
if(u == v) return ret;
if(dep[u] > dep[v]) swap(u, v);
return max(ret, query(tid[son[u]], tid[v], 1, id, 1));
}
char op[15];
int main() {
#ifndef ONLINE_JUDGE
FIN;
#endif // ONLINE_JUDGE
int u, v, w, e;
scanf("%d", &T);
while(T --) {
init();
scanf("%d", &N);
for(int i = 1; i <= N - 1; i ++) {
scanf("%d %d %d", &u, &v, &w);
E[i][0] = u, E[i][1] = v, E[i][2] = w;
add_edge(u, v);
add_edge(v, u);
}
dfs1(1, -1, 1);
dfs2(1, 1);
for(int i = 1; i <= N - 1; i ++) {
if(dep[E[i][0]] > dep[E[i][1]]) swap(E[i][0], E[i][1]);
update(tid[E[i][1]], E[i][2], 1, id, 1);
}
update(tid[1], -1, 1, id, 1);
while(scanf("%s", op) == 1) {
if(op[0] == 'D') break;
if(op[0] == 'C') {
scanf("%d %d", &e, &w);
update(tid[E[e][1]], w, 1, id, 1);
} else {
scanf("%d %d", &u, &v);
printf("%d\n", getAns(u, v));
}
}
}
return 0;
}