学习资料:
http://blog.sina.com.cn/s/blog_7a1746820100wp67.html
题意:给一棵树,两个操作:1、修改某条边的权值;2、查询任意两点的路径上的最大权值。
代码如下:
#include<iostream>
#include<algorithm>
#include<stdio.h>
#include<math.h>
#include<cstring>
#include<string>
#include<vector>
#define inf 0x3f3f3f3f
#define pi acos(-1.0)
#define eps 10e-6
#define N 10005
using namespace std;
struct edge{
int v,w;
};
vector<edge> G[N];
int a[N][5];
//树链剖分部分
//siz[v]表示以v为根的子树的节点数
//dep[v]表示v的深度(根深度为1)
//fa[v]表示v的父亲节点
//top[v]表示v所在的链的顶端节点,fa[v]表示v的父亲
//son[v]表示与v在同一重链上的v的儿子节点(姑且称为重儿子)
//w[v]表示v与其父亲节点的连边(姑且称为v的父边)在线段树中的位置
int son[N],dep[N],siz[N],fa[N];
void dfs1(int u,int pa,int depth)
{
son[u] = 0;
dep[u] = depth;
siz[u] = 1;
fa[u] = pa;
int i,len = G[u].size();
for(i = 0; i < len; i++)
{
int v = G[u][i].v;
if(v == pa) continue;
dfs1(v,u,depth+1);
siz[u] += siz[v];
if(siz[v] > siz[ son[u] ])
son[u] = v;
}
}
int w[N],top[N],dfs_clock;//注意w[1] = 0
void dfs2(int u,int pa)
{
w[u] = dfs_clock++;
top[u] = pa;
if(son[u])
dfs2(son[u], top[u]);
int len = G[u].size();
for(int i = 0; i < len; i++)
{
int v = G[u][i].v;
if(son[u] != v && v != fa[u])
dfs2(v,v);
}
}
//线段树部分
struct node
{
int l,r,max;
}tree[N*4];
void build(int o,int l,int r)
{
tree[o].l = l;
tree[o].r = r;
tree[o].max = -inf;
if(l == r) return ;
int m = (l+r) / 2;
build(2*o,l,m);
build(2*o+1,m+1,r);
}
void update(int o,int pos,int v)
{
if(tree[o].l == tree[o].r) {
tree[o].max = v;
return ;
}
int m = (tree[o].l + tree[o].r)/2;
if(pos <= m) update(2*o,pos,v);
else update(2*o+1,pos,v);
tree[o].max = max( tree[2*o].max, tree[o*2+1].max );
}
int ans;
void query(int o,int x,int y)
{
if(x <= tree[o].l && tree[o].r <= y){
ans = max(ans,tree[o].max);
return;
}
int m = (tree[o].l + tree[o].r)/2;
if(x <= m) query(2*o,x,y);
if(y > m) query(2*o+1,x,y);
}
//树链剖分找点x到点y的最大值
void find(int x,int y)
{
int f1 = top[x],f2 = top[y];
while(f1 != f2)
{
if(dep[f1] < dep[f2]){
swap(f1,f2);
swap(x,y);
}
query(1,w[f1],w[x]);
x = fa[f1];
f1 = top[x];
}
if(x == y) return;
query(1,min(w[x],w[y])+1,max(w[x],w[y]));
}
void output(int o)
{
cout<<o<<" "<<tree[o].l<<" "<<tree[o].r<<" "<<tree[o].max<<endl;
if(tree[o].l == tree[o].r) return ;
output(2*o);
output(2*o+1);
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
int n;
scanf("%d",&n);
int i;
for(i = 0; i <= n; i++) G[i].clear();
for(i = 1; i < n; i++)
{
scanf("%d%d%d",&a[i][0],&a[i][1],&a[i][2]);
edge temp;
temp.v = a[i][1];
temp.w = a[i][2];
G[ a[i][0] ].push_back(temp);
temp.v = a[i][0];
G[ a[i][1] ].push_back(temp);
}
memset(siz,0,sizeof(siz));
memset(son,0,sizeof(son));
memset(fa,0,sizeof(fa));
memset(dep,0,sizeof(dep));
dfs1(1,1,1);
dfs_clock = 0;
dfs2(1,1);
build(1,1,n-1);
for(i = 1; i < n; i++)
{
if(dep[ a[i][0] ] < dep[ a[i][1] ])
swap(a[i][0],a[i][1]);
update(1,w[ a[i][0] ], a[i][2]);
}
// output(1);
char s[10];
while(scanf("%s",s)){
if(s[0] == 'D') break;
int x,y;
scanf("%d%d",&x,&y);
if(s[0] == 'C'){
update(1,w[ a[x][0] ], y);
}
else{
ans = -inf;
find(x,y);
printf("%d\n",ans);
}
}
}
return 0;
}
/*
1
14
1 2 9
1 3 7
1 4 1
2 5 13
2 6 10
3 7 8
4 8 6
4 9 2
4 10 5
6 11 11
6 12 12
9 13 3
13 14 4
1 10 8 2 14 11 9 7 3 6 13 12 4 5
1
3
1 2 1
2 3 2
*/