题目链接:http://www.spoj.com/problems/QTREE/
题意:
T个测试案例
n个点的树
下面n-1条边和边权
change u v 把第u-th给出的边 的边权改为v
query 询问路径 [u, v] 间最大的边权
#include<stdio.h> #include<iostream> #include<string.h> #include<math.h> #include<algorithm> #define N 10010 #define L(x) (x<<1) #define R(x) (x<<1|1) #define Mid(x,y) ((x+y)>>1) using namespace std; struct Edge{ int from, to, nex; }edge[N<<1]; int head[N], edgenum; void add(int u, int v){ Edge E={u, v, head[u]}; edge[edgenum] = E; head[u] = edgenum++; } int fa[N], siz[N], son[N], w[N], p[N], dep[N], tree_id; int fp[N];//和p数组相反 //给每条边编号 边(u, v),设dep[u]<dep[v](v在下面) 用v来表示边的编号 //w[v] 表示v所在的父边 在线段树中的位置 void dfs(int u, int father, int deep){ son[u] = 0; fa[u] = father; siz[u] = 1; dep[u] = deep; for(int i = head[u]; ~i; i = edge[i].nex){ int v = edge[i].to; if(v == father)continue; dfs(v, u, deep+1); siz[u] += siz[v]; if(siz[v] > siz[ son[u] ])son[u] = v; } } void Have_p(int u, int father){ w[u] = ++tree_id; p[u] = father; if(son[u]) Have_p(son[u], father); else return; for(int i = head[u]; ~i; i = edge[i].nex) { int v = edge[i].to; if(v != fa[u] && v != son[u]) Have_p(v, v); } } struct node{ int l, r; int Max; }tree[N*4]; void build(int l, int r, int id){ tree[id].l = l, tree[id].r = r; tree[id].Max = 0; if(l == r)return ; int mid = Mid(l,r); build(l, mid, L(id)); build(mid+1, r, R(id)); } void updata(int pos, int val, int id){ if(tree[id].l == tree[id].r) { tree[id].Max = val; return ; } int mid = Mid(tree[id].l, tree[id].r); if(pos <= mid) updata(pos, val, L(id)); else updata(pos, val, R(id)); tree[id].Max = max(tree[L(id)].Max, tree[R(id)].Max); } int query(int l, int r, int id){ if(l == tree[id].l && tree[id].r == r) return tree[id].Max; int mid = Mid(tree[id].l, tree[id].r); if(r<=mid) return query(l, r, L(id)); else if(mid<l) return query(l, r, R(id)); else return max(query(l, mid, L(id)), query(mid+1, r, R(id))); } int find(int u, int v){ int f1 = p[u], f2 = p[v]; int tmp = 0; while(f1 != f2) { if(dep[f1] < dep[f2]) swap(f1, f2), swap(u, v); tmp = max(tmp, query(w[f1], w[u], 1)); u = fa[f1], f1 = p[u]; } if(u == v)return tmp; if(dep[u] > dep[v])swap(u, v); return max(tmp, query(w[son[u]], w[v], 1)); } int n; int D[N][3]; void init(){ memset(head, -1, sizeof(head)); edgenum = 0; memset(son, 0, sizeof(son));//这个的初始化 tree_id = 0; } int main(){ int T;scanf("%d",&T); int i, u, v, d; char s[10]; while(T--){ scanf("%d",&n); init(); for(i=1;i<n;i++) { scanf("%d %d %d", &u,&v,&d); D[i][0] = u, D[i][1] = v, D[i][2] = d; add(u, v), add(v, u); } dfs(1, 1, 0); Have_p(1, 1); build(1, n, 1); for(i=1;i<n;i++) { //int u = D[i][0], v = D[i][1], d = D[i][2]; //if(dep[u]>dep[v]) swap(u, v)因为 w[v] 是表示父边,显然是深度大的v才能表示父边 if(dep[ D[i][0] ] > dep[ D[i][1] ])swap(D[i][0], D[i][1]); updata(w[ D[i][1] ], D[i][2], 1); } while(scanf("%s",s)) { if(s[0] == 'D')break; scanf("%d %d", &u, &v); if(s[0] == 'C') updata(w[D[u][1]], v, 1); else printf("%d\n", find(u,v)); } } return 0; }