Description
You are given a tree (an acyclic undirected connected graph) with
N
nodes, and edges numbered 1, 2, 3…
We will ask you to perfrom some instructions of the following form:
CHANGE
i
or
QUERY
a
Input
The first line of input contains an integer
t
, the number of test cases
For each test case:
In the first line there is an integer
In the next
N−1
lines, the
i
-th line describes the
The next lines contain instructions “CHANGE
i
The end of each test case is signified by the string “DONE”.
There is one blank line between successive tests.
Output
For each “QUERY” operation, write one integer representing its result.
Sample Input
1
3
1 2 1
2 3 2
QUERY 1 2
CHANGE 1 3
QUERY 1 2
DONE
Sample Output
1
3
题目解释
给一棵共有
n(n<=10000)
个结点的树,每条边都有一个权值,要求维护一个数据结构,支持如下操作:
1. 修改某条边的权值;
2. 询问某两个结点之间的唯一通路上的最大边权。
其中操作的总次数为 q。
思路
树链剖分水题(其实也不是很水),把边权放到每个点就可以了。
代码
#include <cstdio>
#include <algorithm>
#include <cstring>
const int maxn=10000;
const int inf=1000000000;
struct sigment_tree
{
int val[(maxn<<2)+10];
int updata(int now)
{
val[now]=std::max(val[now<<1],val[now<<1|1]);
return 0;
}
int build(int now,int left,int right)
{
if(left==right)
{
val[now]=0;
return 0;
}
int mid=(left+right)>>1;
build(now<<1,left,mid);
build(now<<1|1,mid+1,right);
updata(now);
return 0;
}
int modify(int now,int left,int right,int findnum,int changeval)
{
if((findnum<left)||(findnum>right))
{
return 0;
}
if(left==right)
{
val[now]=changeval;
return 0;
}
int mid=(left+right)>>1;
modify(now<<1,left,mid,findnum,changeval);
modify(now<<1|1,mid+1,right,findnum,changeval);
updata(now);
return 0;
}
int ask(int now,int left,int right,int askl,int askr)
{
if((askr<left)||(askl>right))
{
return -inf;
}
if((askl<=left)&&(askr>=right))
{
return val[now];
}
int mid=(left+right)>>1;
return std::max(ask(now<<1,left,mid,askl,askr),ask(now<<1|1,mid+1,right,askl,askr));
}
};
struct data
{
int start,end;
};
int n;
data d[maxn+10];
struct tree
{
int pre[(maxn<<1)+10],now[maxn+10],son[(maxn<<1)+10],tot,val[(maxn<<1)+10];
int fa[maxn+10],wson[maxn+10],deep[maxn+10],dfn[maxn+10],cnt,top[maxn+10],size[maxn+10];
sigment_tree st;
int mem()
{
memset(pre,0,sizeof pre);
memset(now,0,sizeof now);
memset(son,0,sizeof son);
memset(val,0,sizeof val);
memset(fa,0,sizeof fa);
memset(wson,0,sizeof wson);
memset(deep,0,sizeof deep);
memset(dfn,0,sizeof dfn);
memset(top,0,sizeof top);
memset(size,0,sizeof size);
tot=0;
cnt=0;
return 0;
}
int ins(int a,int b,int c)
{
tot++;
pre[tot]=now[a];
now[a]=tot;
son[tot]=b;
val[tot]=c;
return 0;
}
int change(int pos,int val)
{
st.modify(1,1,n,dfn[pos],val);
return 0;
}
int first_dfs(int u,int father)
{
deep[u]=deep[father]+1;
fa[u]=father;
size[u]=1;
wson[u]=0;
int j=now[u];
while(j)
{
int v=son[j];
if(v!=father)
{
first_dfs(v,u);
size[u]+=size[v];
if((!wson[u])||(size[v]>size[wson[u]]))
{
wson[u]=v;
}
}
j=pre[j];
}
return 0;
}
int second_dfs(int u,int father,int topfather)
{
cnt++;
dfn[u]=cnt;
top[u]=topfather;
if(wson[u])
{
second_dfs(wson[u],u,topfather);
}
int j=now[u];
while(j)
{
int v=son[j];
if((v!=father)&&(v!=wson[u]))
{
second_dfs(v,u,v);
}
j=pre[j];
}
return 0;
}
int third_dfs(int u,int father,int pointval)
{
change(u,pointval);
int j=now[u];
while(j)
{
int v=son[j];
if(v!=father)
{
third_dfs(v,u,val[j]);
if(!(j&1))
{
std::swap(d[(j+1)/2].start,d[(j+1)/2].end);
}
}
j=pre[j];
}
return 0;
}
int ask(int x,int y)
{
int res=-inf;
while(top[x]!=top[y])
{
if(deep[top[x]]<deep[top[y]])
{
std::swap(x,y);
}
res=std::max(st.ask(1,1,n,dfn[top[x]],dfn[x]),res);
x=fa[top[x]];
}
if(deep[x]>deep[y])
{
std::swap(x,y);
}
res=std::max(st.ask(1,1,n,dfn[wson[x]],dfn[y]),res);
return res;
}
};
tree t;
int solve()
{
scanf("%d",&n);
t.mem();
t.st.build(1,1,n);
for(int i=1; i<n; i++)
{
int c;
scanf("%d%d%d",&d[i].start,&d[i].end,&c);
t.ins(d[i].start,d[i].end,c);
t.ins(d[i].end,d[i].start,c);
}
t.first_dfs(1,0);
t.second_dfs(1,0,1);
t.third_dfs(1,0,-inf);
while(1)
{
char s[10];
int a,b;
scanf("%s",s);
if(s[0]=='C')
{
scanf("%d%d",&a,&b);
t.change(d[a].end,b);
}
if(s[0]=='Q')
{
scanf("%d%d",&a,&b);
printf("%d\n",t.ask(a,b));
}
if(s[0]=='D')
{
break;
}
}
return 0;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
solve();
}
return 0;
}