You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3…N-1.
We will ask you to perfrom some instructions of the following form:
CHANGE i ti : change the cost of the i-th edge to ti
or
QUERY a b : ask for the maximum edge cost on the path from node a to node b
Input
The first line of input contains an integer t, the number of test cases (t <= 20). t test cases follow.
For each test case:
In the first line there is an integer N (N <= 10000),
In the next N-1 lines, the i-th line describes the i-th edge: a line with three integers a b c denotes an edge between a, b of cost c (c <= 1000000),
The next lines contain instructions “CHANGE i ti” or “QUERY a b”,
The end of each test case is signified by the string “DONE”.
There is one blank line between successive tests.
For each “QUERY” operation, write one integer representing its result.
1
3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE
1
3
树链剖分裸题……边权赋给点上,注意边界。
#include<cstdio>
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
const int size=200010;
int head[size],nxt[size],tot=0;
struct edge{
int t,d;
}l[size];
void build(int f,int t,int d)
{
l[++tot].t=t;
l[tot].d=d;
nxt[tot]=head[f];
head[f]=tot;
}
int deep[size],top[size],inseg[size];
int fa[size],son[size],sz[size];
void dfs_1(int u,int f)
{
fa[u]=f;
deep[u]=deep[f]+1;
sz[u]=1;
for(int i=head[u];i;i=nxt[i])
{
int v=l[i].t;
if(v==f) continue;
dfs_1(v,u);
sz[u]+=sz[v];
if(!son[u]||sz[v]>sz[son[u]]) son[u]=v;
}
}
int totp=0;
void dfs_2(int u,int topu)
{
top[u]=topu;
inseg[u]=++totp;
if(!son[u]) return ;
dfs_2(son[u],topu);
for(int i=head[u];i;i=nxt[i])
{
int v=l[i].t;
if(v==fa[u]||v==son[u]) continue;
dfs_2(v,v);
}
}
struct segment{
int l,r;
int maxx;
}tree[size*4];
void update(int p)
{
tree[p].maxx=max(tree[p<<1].maxx,tree[p<<1|1].maxx);
}
void build_tree(int p,int l,int r)
{
tree[p].l=l; tree[p].r=r;
if(l==r)
{
tree[p].maxx=0;
return ;
}
int mid=(l+r)>>1;
build_tree(p<<1,l,mid);
build_tree(p<<1|1,mid+1,r);
update(p);
}
void change(int p,int x,int d)
{
if(tree[p].l==tree[p].r)
{
tree[p].maxx=d;
return ;
}
int mid=(tree[p].l+tree[p].r)>>1;
if(x<=mid) change(p<<1,x,d);
else change(p<<1|1,x,d);
update(p);
}
int ask_max(int p,int l,int r)
{
if(l<=tree[p].l&&tree[p].r<=r)
{
return tree[p].maxx;
}
int mid=(tree[p].l+tree[p].r)>>1;
int ans=0;
if(l<=mid) ans=max(ans,ask_max(p<<1,l,r));
if(mid<r) ans=max(ans,ask_max(p<<1|1,l,r));
return ans;
}
int find_max(int x,int y)
{
int fx=top[x],fy=top[y];
int ans=0;
while(fx!=fy)
{
if(deep[fx]<deep[fy]) swap(fx,fy),swap(x,y);
ans=max(ans,ask_max(1,inseg[fx],inseg[x]));
x=fa[fx];fx=top[x];
}
if(x!=y)
{
if(deep[x]>deep[y]) swap(x,y);
ans=max(ans,ask_max(1,inseg[x]+1,inseg[y]));
}
return ans;
}
int n;
int ff[size],tt[size],dd[size];
void init()
{
memset(head,0,sizeof(head));
memset(nxt,0,sizeof(nxt));
memset(l,0,sizeof(l));
memset(deep,0,sizeof(deep));
memset(top,0,sizeof(top));
memset(inseg,0,sizeof(inseg));
memset(fa,0,sizeof(fa));
memset(son,0,sizeof(son));
memset(sz,0,sizeof(sz));
memset(ff,0,sizeof(ff));
memset(tt,0,sizeof(tt));
memset(dd,0,sizeof(dd));
memset(tree,0,sizeof(tree));
tot=0;
totp=0;
}
char in[233];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
init();
scanf("%d",&n);
for(int i=1;i<=n-1;i++)
{
scanf("%d%d%d",&ff[i],&tt[i],&dd[i]);
build(ff[i],tt[i],dd[i]);
build(tt[i],ff[i],dd[i]);
}
dfs_1(1,0);
dfs_2(1,1);
build_tree(1,1,n);
for(int i=1;i<=n-1;i++)
{
if(deep[ff[i]]>deep[tt[i]]) swap(ff[i],tt[i]);
change(1,inseg[tt[i]],dd[i]);
}
while(233)
{
int a,b;
scanf("%s",in);
if(in[0]=='D') break;
scanf("%d%d",&a,&b);
if(in[0]=='C') change(1,inseg[tt[a]],b);
else printf("%d\n",find_max(a,b));
//for(int i=1;i<=n;i++) printf("%d ",ask_max(1,inseg[i],inseg[i]));puts("");
}
puts("");
}
return 0;
}
/* 1 7 1 3 5 5 3 2 1 2 1 1 4 3 5 7 7 3 6 4 QUERY 7 4 QUERY 5 6 QUERY 2 7 CHANGE 5 2 */