Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 3189 | Accepted: 897 |
Description
You are given a tree with N nodes. The tree’s nodes are numbered 1 throughN 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 integert (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 containsN (N ≤ 10,000). The next N − 1 lines each contains three integersa, 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
题意:给定一颗树,有三种操作:(1)改变第i条边的权值,(2)将从u到v路径上的权值取反,(3)查询从u到v路径上的最大权。
解题思路:首先轻重链剖分,然后线段树维护最大值,最小值,以及取反标记。
代码:
/* ***********************************************
Author :xianxingwuguan
Created Time :2014-1-24 13:55:10
File Name :2.cpp
************************************************ */
#pragma comment(linker, "/STACK:102400000,102400000")
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <algorithm>
#include <vector>
#include <queue>
#include <set>
#include <map>
#include <string>
#include <math.h>
#include <stdlib.h>
#include <time.h>
using namespace std;
const int maxn=110000;
const int inf=1000000000;
int head[maxn],tol,top[maxn],p[maxn],fp[maxn],num[maxn],fa[maxn],son[maxn],deep[maxn],pos;
struct node
{
int next,to;
}edge[10*maxn];
void add(int u,int v)
{
edge[tol].next=head[u];
edge[tol].to=v;
head[u]=tol++;
}
void init()
{
memset(head,-1,sizeof(head));
tol=0;
memset(son,-1,sizeof(son));
pos=0;
}
void dfs(int u,int pre,int d)
{
deep[u]=d;
num[u]=1;
fa[u]=pre;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(v==pre)continue;
dfs(v,u,d+1);
num[u]+=num[v];
if(son[u]==-1||num[v]>num[son[u]])
son[u]=v;
}
}
void getpos(int u,int sp)
{
top[u]=sp;
p[u]=pos++;
fp[p[u]]=u;
if(son[u]==-1)return;
getpos(son[u],sp);
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(v!=fa[u]&&v!=son[u])
getpos(v,v);
}
}
struct NODE
{
int l,r,max,min,neg;
}tree[6*maxn];
void pushup(int i)
{
tree[i].max=max(tree[2*i].max,tree[2*i+1].max);
tree[i].min=min(tree[2*i].min,tree[2*i+1].min);
}
void pushdown(int i)
{
if(tree[i].l==tree[i].r)return;
if(tree[i].neg)
{
tree[2*i].max=-tree[2*i].max;
tree[2*i].min=-tree[2*i].min;
swap(tree[2*i].max,tree[2*i].min);
tree[2*i].neg^=1;
tree[2*i+1].max=-tree[2*i+1].max;
tree[2*i+1].min=-tree[2*i+1].min;
swap(tree[2*i+1].max,tree[2*i+1].min);
tree[2*i+1].neg^=1;
tree[i].neg=0;
}
}
void build(int l,int r,int i)
{
tree[i].l=l;
tree[i].r=r;
tree[i].neg=0;
tree[i].max=0;
tree[i].min=0;
if(l==r)return;
int mid=(l+r)/2;
build(l,mid,2*i);
build(mid+1,r,2*i+1);
}
void update1(int i,int pos,int val)
{
if(tree[i].l==tree[i].r)
{
tree[i].max=tree[i].min=val;
tree[i].neg=0;
return;
}
pushdown(i);
int mid=(tree[i].l+tree[i].r)>>1;
if(pos<=mid)update1(2*i,pos,val);
else update1(2*i+1,pos,val);
pushup(i);
}
void negval(int i,int l,int r)
{
if(tree[i].l>=l&&tree[i].r<=r)
{
tree[i].max=-tree[i].max;
tree[i].min=-tree[i].min;
swap(tree[i].max,tree[i].min);
tree[i].neg^=1;
return;
}
pushdown(i);
int mid=(tree[i].l+tree[i].r)>>1;
if(l<=mid)negval(2*i,l,r);
if(r>mid)negval(2*i+1,l,r);
pushup(i);
}
int query(int i,int l,int r)
{
if(tree[i].l>=l&&tree[i].r<=r)return tree[i].max;
pushdown(i);
int mid=(tree[i].l+tree[i].r)>>1;
int ans=-inf;
if(l<=mid)ans=max(ans,query(2*i,l,r));
if(r>mid)ans=max(ans,query(2*i+1,l,r));
pushup(i);
return ans;
}
int findmax(int u,int v)
{
int f1=top[u],f2=top[v];
int tmp=-inf;
while(f1!=f2)
{
if(deep[f1]<deep[f2])
{
swap(f1,f2);
swap(u,v);
}
tmp=max(tmp,query(1,p[f1],p[u]));
u=fa[f1];
f1=top[u];
}
if(u==v)return tmp;
if(deep[u]>deep[v])swap(u,v);
return max(tmp,query(1,p[son[u]],p[v]));
}
void neg(int u,int v)
{
int f1=top[u],f2=top[v];
while(f1!=f2)
{
if(deep[f1]<deep[f2])
{
swap(f1,f2);
swap(u,v);
}
negval(1,p[f1],p[u]);
u=fa[f1];
f1=top[u];
}
if(u==v)return;
if(deep[u]>deep[v])swap(u,v);
negval(1,p[son[u]],p[v]);
}
int e[maxn][3];
int main()
{
// freopen("tree.in","r",stdin);
// freopen("data.out","w",stdout);
int T,n;
scanf("%d",&T);
while(T--)
{
init();
scanf("%d",&n);
for(int i=0;i<n-1;i++)
{
scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]);
add(e[i][0],e[i][1]);
add(e[i][1],e[i][0]);
}
dfs(1,0,0);
getpos(1,1);
// cout<<pos<<endl;
build(0,pos-1,1);
for(int i=0;i<n-1;i++)
{
if(deep[e[i][0]]>deep[e[i][1]])
swap(e[i][0],e[i][1]);
update1(1,p[e[i][1]],e[i][2]);
}
char op[10];
int u,v;
while(~scanf("%s",op))
{
if(op[0]=='D')break;
scanf("%d%d",&u,&v);
if(op[0]=='Q')
printf("%d\n",findmax(u,v));
else if(op[0]=='C')
update1(1,p[e[u-1][1]],v);
else neg(u,v);
}
}
return 0;
}