Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 6101 | Accepted: 1671 |
Description
You are given a tree with N nodes. The tree’s nodes are numbered 1 through N and its edges are numbered 1 through N − 1. Each edge is associated with a weight. Then you are to execute a series of instructions on the tree. The instructions can be one of the following forms:
CHANGE i v | Change the weight of the ith edge to v |
NEGATE a b | Negate the weight of every edge on the path from a to b |
QUERY a b | Find the maximum weight of edges on the path from a to b |
Input
The input contains multiple test cases. The first line of input contains an integer t (t ≤ 20), the number of test cases. Then follow the test cases.
Each test case is preceded by an empty line. The first nonempty line of its contains N (N ≤ 10,000). The next N − 1 lines each contains three integers a, b and c, describing an edge connecting nodes a and b with weight c. The edges are numbered in the order they appear in the input. Below them are the instructions, each sticking to the specification above. A lines with the word “DONE
” ends the test case.
Output
For each “QUERY
” instruction, output the result on a separate line.
Sample Input
1 3 1 2 1 2 3 2 QUERY 1 2 CHANGE 1 3 QUERY 1 2 DONE
Sample Output
1 3
题意:给你一棵树,边上有权值,更新操作有将一个路径上的值取反,和更改一个点的值。查询操作查询两个点之间路径的最大边值。
思路:树链刨分,就是线段树敲起来复杂了些。
AC代码如下:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
struct node1
{
int u,v,w;
}arr[10010];
struct node2
{
int u,v,w,next;
}edge[20010];
struct node3
{
int l,r,maxn,minn,lazy;
}tree[40010];
int T,t,n,m,tot,tot2,Head[10010],INF=1e9;
int siz[10010],son[10010],depth[10010],fa[10010],top[10010],p[10010];
int W[10010];
char s[10];
void dfs1(int u)
{
int i,j,k,v;
siz[u]=1;
son[u]=0;
for(i=Head[u];i!=-1;i=edge[i].next)
{
v=edge[i].v;
if(v==fa[u])
continue;
depth[v]=depth[u]+1;
fa[v]=u;
dfs1(v);
if(siz[v]>siz[son[u]])
son[u]=v;
siz[u]+=siz[v];
}
}
void dfs2(int u,int f)
{
int i,j,k,v;
p[u]=++tot2;
top[u]=f;
if(son[u]!=0)
dfs2(son[u],f);
for(i=Head[u];i!=-1;i=edge[i].next)
{
v=edge[i].v;
if(v==fa[u] || v==son[u])
continue;
dfs2(v,v);
}
}
void add(int u,int v,int w)
{
edge[tot].u=u;
edge[tot].v=v;
edge[tot].w=w;
edge[tot].next=Head[u];
Head[u]=tot++;
}
void up(int tr)
{
tree[tr].maxn=max(tree[tr*2].maxn,tree[tr*2+1].maxn);
tree[tr].minn=min(tree[tr*2].minn,tree[tr*2+1].minn);
}
void op(int tr)
{
tree[tr].maxn=-tree[tr].maxn;
tree[tr].minn=-tree[tr].minn;
swap(tree[tr].maxn,tree[tr].minn);
}
void down(int tr)
{
int minn,maxn;
if(tree[tr].lazy)
{
tree[tr].lazy=0;
tree[tr*2].lazy=(tree[tr*2].lazy+1)%2;
tree[tr*2+1].lazy=(tree[tr*2+1].lazy+1)%2;
op(tr*2);
op(tr*2+1);
}
}
void build(int l,int r,int tr)
{
tree[tr].l=l;
tree[tr].r=r;
tree[tr].lazy=0;
if(l==r)
{
tree[tr].maxn=tree[tr].minn=W[l];
return;
}
int mi=(l+r)/2;
build(l,mi,tr*2);
build(mi+1,r,tr*2+1);
up(tr);
}
void update1(int l,int r,int tr)
{
if(tree[tr].l==l && tree[tr].r==r)
{
tree[tr].lazy=(tree[tr].lazy+1)%2;
op(tr);
return;
}
down(tr);
int mi=(tree[tr].l+tree[tr].r)/2;
if(r<=mi)
update1(l,r,tr*2);
else if(l>mi)
update1(l,r,tr*2+1);
else
{
update1(l,mi,tr*2);
update1(mi+1,r,tr*2+1);
}
up(tr);
}
void update2(int id,int tr,int num)
{
if(tree[tr].l==tree[tr].r)
{
tree[tr].maxn=tree[tr].minn=num;
return;
}
down(tr);
int mi=(tree[tr].l+tree[tr].r)/2;
if(id<=mi)
update2(id,tr*2,num);
else
update2(id,tr*2+1,num);
up(tr);
}
int query(int l,int r,int tr)
{
if(tree[tr].l==l && tree[tr].r==r)
return tree[tr].maxn;
down(tr);
int mi=(tree[tr].l+tree[tr].r)/2;
if(r<=mi)
return query(l,r,tr*2);
else if(l>mi)
return query(l,r,tr*2+1);
else
return max(query(l,mi,tr*2),query(mi+1,r,tr*2+1));
}
int solve(int u,int v,int type)
{
int f1=top[u],f2=top[v],k,maxn=-INF;
while(f1!=f2)
{
if(depth[f1]<depth[f2])
{
swap(f1,f2);
swap(u,v);
}
if(type==1)
update1(p[f1],p[u],1);
else
maxn=max(maxn,query(p[f1],p[u],1));
u=fa[f1];
f1=top[u];
}
if(u==v)
return maxn;
if(depth[u]>depth[v])
swap(u,v);
if(type==1)
update1(p[son[u]],p[v],1);
else
maxn=max(maxn,query(p[son[u]],p[v],1));
return maxn;
}
int main()
{
int i,j,k,u,v,w,pos,ans;
scanf("%d",&T);
for(t=1;t<=T;t++)
{
scanf("%d",&n);
tot=tot2=0;
memset(Head,-1,sizeof(Head));
for(i=1;i<n;i++)
{
scanf("%d%d%d",&u,&v,&w);
arr[i].u=u;
arr[i].v=v;
arr[i].w=w;
add(u,v,w);
add(v,u,w);
}
depth[1]=1;
dfs1(1);
dfs2(1,1);
for(i=1;i<n;i++)
{
if(arr[i].v==fa[arr[i].u])
swap(arr[i].v,arr[i].u);
W[p[arr[i].v]]=arr[i].w;
}
build(1,tot2,1);
while(true)
{
scanf("%s",s+1);
if(s[1]=='C')
{
scanf("%d%d",&i,&w);
update2(p[arr[i].v],1,w);
}
else if(s[1]=='N')
{
scanf("%d%d",&u,&v);
solve(u,v,1);
}
else if(s[1]=='Q')
{
scanf("%d%d",&u,&v);
ans=solve(u,v,2);
printf("%d\n",ans);
}
else
break;
}
}
}