题目链接: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;
}