题目链接:http://www.spoj.com/problems/QTREE/
题意:给一棵树,单点更新, 询问树上两点间路径上边权最大值。
树链剖分模板题,
学习资料:
参考bin神代码:
http://www.cnblogs.com/kuangbin/p/3253741.html
具体步骤: 来自 http://hzwer.com/category/c/graphtheory/tree-algorithm/tree-chain-partition
#include <bits/stdc++.h>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn = 1e4+10;
struct Edge{
int to, next;
}e[maxn*2];
// 前向星
int cnt, head[maxn];
int n;
int x[maxn], y[maxn], z[maxn];
// 树链剖分
int fa[maxn], dep[maxn], size[maxn];
int son[maxn]; // 重儿子
int top[maxn]; // top[v] 代表v所在的重链的顶端结点
int idx[maxn]; // idx[v] 代表v与其父亲的边在线段树中的标号
int fidx[maxn]; // 与idx相反
int pos;
//线段树
int Max[maxn<<2];
void init()
{
cnt = 0;
pos = 0;
memset(head, -1, sizeof(head));
memset(son, -1, sizeof(son));
}
void add(int u, int v)
{
e[cnt].to = v;
e[cnt].next = head[u];
head[u] = cnt++;
}
// 第一次dfs, 找出所有重边
void dfs1(int u, int pre, int d)
{
fa[u] = pre; size[u] = 1; dep[u] = d;
for(int i=head[u]; i!=-1; i=e[i].next)
{
int v = e[i].to;
if(v == pre) continue;
dfs1(v, u, d+1);
size[u] += size[v];
if(son[u] == -1 || size[v] > size[son[u]]) son[u] = v;
}
}
// 第二次dfs,连重边成重链,并且给每个结点重新标号(重链构成连续的区间)
void dfs2(int u, int anc)
{
top[u] = anc;
if( son[u] != -1)
{
idx[u] = pos++;
fidx[idx[u]] = u;
dfs2(son[u], anc);
}
else
{
idx[u] = pos++;
fidx[idx[u]] = u;
return;
}
for(int i=head[u]; i!=-1; i=e[i].next)
{
int v = e[i].to;
if(v != fa[u] && v!=son[u]) dfs2(v, v);
}
}
void pushUp(int rt)
{
Max[rt] = max(Max[rt<<1], Max[rt<<1|1]);
}
void update(int p, int v, int l, int r, int rt)
{
if(l == r)
{
Max[rt] = v;
return;
}
int m = (l + r) >> 1;
if(p <= m) update(p, v, lson);
else update(p, v, rson);
pushUp(rt);
}
int query(int L, int R, int l, int r, int rt)
{
if(L <=l && r <= R) return Max[rt];
int ret = 0;
int m = (l + r) >> 1;
if(L <= m) ret = max(ret, query(L, R, lson));
if(R > m) ret = max(ret, query(L, R, rson));
return ret;
}
int solve(int u, int v)
{
int ret = 0;
int f1 = top[u], f2 = top[v];
while( f1 != f2)
{
if(dep[f1] < dep[f2])
{
swap(f1, f2);
swap(u, v);
}
ret = max(ret, query(idx[f1], idx[u], 0, pos-1, 1));
u = fa[f1]; f1 = top[u];
}
if(u == v) return ret;
if(dep[u] > dep[v]) swap(u, v);
return max(ret, query(idx[son[u]], idx[v], 0, pos-1, 1));
}
int main()
{
int t, a, b;
char buf[10];
cin >> t;
while(t--)
{
init();
scanf("%d", &n);
for(int i=1;i<=n-1;i++)
{
scanf("%d%d%d", &x[i], &y[i], &z[i]);
add(x[i], y[i]);
add(y[i], x[i]);
}
dfs1(1, -1, 0); dfs2(1, 1);
memset(Max, 0, sizeof(Max));
// for(int i=1; i<=n; i++)
// {
// printf("son:%d size:%d dep:%d id:%d\n", son[i], size[i], dep[i], idx[i]);
// }
for(int i=1; i<n; i++)
{
if(dep[x[i]] > dep[y[i]]) swap(x[i], y[i]);
update(idx[y[i]], z[i], 0, pos-1, 1);
}
while( scanf("%s", buf) )
{
if(buf[0] == 'D') break;
scanf("%d%d", &a, &b);
if(buf[0] == 'Q') printf("%d\n", solve(a, b));
else update(idx[y[a]], b, 0, pos-1, 1);
}
}
return 0;
}