学了下树链剖分,这个链接讲的很详细http://blog.sina.com.cn/s/blog_6974c8b20100zc61.html
就是把一颗树划分轻重链,然后标号,对应到一颗线段树上。更新a到b的路径时,就把在下面的向上提 直到在一条重链上或者两点重合。
#include <cstdio> #include <algorithm> #include <iostream> #include <string.h> using namespace std; #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 const int maxn = 111111; struct Node { int to;int val;int next; }e[maxn]; int edge[maxn][3]; int len ; int z; ; int son[maxn]; int father[maxn]; int size[maxn]; int deep[maxn]; int pos[maxn],top[maxn]; int Max[maxn<<2]; int head[maxn]; void add(int from, int to, int val) { e[len].to = to; e[len].val = val; e[len].next = head[from]; head[from] = len++; } void init(int x) { size[x] = 1; son[x] = 0; for (int i = head[x]; i != -1; i = e[i].next){ int cc = e[i].to; if (cc == father[x]) continue; father[cc] = x; deep[cc] = deep[x] + 1; init(cc); if (size[cc] > size[son[x]]) son[x] = cc; size[x]+=size[cc]; } } void dfs(int x, int tp) { pos[x] = ++z; top[x] = tp; if (son[x]) dfs(son[x], tp); for (int i = head[x]; i != -1; i = e[i].next){ int cc = e[i].to; if (cc == son[x] || cc == father[x]) continue; dfs(cc, cc); } } void up(int rt) { Max[rt] = max(Max[rt << 1], Max[rt << 1 | 1]); } void update(int pos, int key, int l, int r, int rt) { if (l == r){ Max[rt] = key; return; } int mid = (l + r) >> 1; if (pos <= mid) update(pos, key, lson); else update(pos, key, rson); up(rt); } int ask(int L, int R, int l, int r, int rt) { if (L <= l&&r <= R) return Max[rt]; int mid = (l + r) >> 1; int ans = -1; if (L <= mid) ans = max(ans, ask(L, R, lson)); if (R > mid) ans = max(ans, ask(L, R, rson)); return ans; } int gao(int x, int y) { int ans = -1; int f1 = top[x]; int f2 = top[y]; while (f1 != f2){ if (deep[f1] < deep[f2]){ swap(f1, f2); swap(x, y); } ans = max(ans, ask(pos[f1], pos[x], 1, z, 1)); x = father[f1]; f1 = top[x]; } if (x == y) return ans; if (deep[x]>deep[y]) swap(x, y); ans = max(ans ,ask(pos[son[x]],pos[y],1,z,1)); return ans; } int main() { char str[100]; int Icase; int n; cin >> Icase; while (Icase--){ cin >> n; memset(size,0,sizeof(size)); memset(Max,0,sizeof(Max)); z = 0; len = 0; memset(head, -1, sizeof(head)); for (int i = 1; i < n; i++){ scanf("%d%d%d", &edge[i][0], &edge[i][1], &edge[i][2]); add(edge[i][0], edge[i][1], edge[i][2]); add(edge[i][1], edge[i][0], edge[i][2]); } init(1); dfs(1, 1); for (int i = 1; i < n ; i++){ int a = edge[i][0]; int b = edge[i][1]; int c = edge[i][2]; if (deep[a]>deep[b]) swap(edge[i][0], edge[i][1]); update(pos[edge[i][1]], c, 1, z, 1); } while (scanf("%s", str) != EOF){ if (str[0] == 'D') break; int a; int b; scanf("%d%d", &a, &b); if (str[0] == 'C'){ update(pos[edge[a][1]], b, 1, z, 1); } else { printf("%d\n", gao(a, b)); } } } return 0; }