Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 4849 | Accepted: 1327 |
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
树链剖分完之后就跟普通的线段树一样了
#include<iostream>
#include<cstdio>
#include<string>
#include<cstring>
#include<vector>
#include<cmath>
#include<queue>
#include<stack>
#include<map>
#include<set>
#include<algorithm>
using namespace std;
const int maxn=11010;
const int INF=1000000000;
struct node
{
int a,b,w;
}e[maxn];
int N;
int head[maxn];
int top[maxn],tot;
int deep[maxn];
int fa[maxn];
int w[maxn],fw[maxn];
int num[maxn];
int son[maxn];
int pos;
struct Edge
{
int v,next;
}edge[maxn*2];
void init()
{
tot=pos=0;
memset(head,-1,sizeof(head));
memset(son,-1,sizeof(son));
}
void add_edge(int u,int v)
{
edge[tot].v=v;
edge[tot].next=head[u];
head[u]=tot++;
}
void dfs1(int u,int pre,int d)
{
deep[u]=d;
fa[u]=pre;
num[u]=1;
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(v==pre)continue;
dfs1(v,u,d+1);
num[u]+=num[v];
if(son[u]==-1||num[son[u]]<num[v])
son[u]=v;
}
}
void dfs2(int u,int sp)
{
top[u]=sp;
w[u]=pos++;
fw[w[u]]=u;
if(son[u]==-1)return ;
dfs2(son[u],sp);
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].v;
if(v!=fa[u]&&v!=son[u])
dfs2(v,v);
}
}
struct IntervalTree
{
int maxv[maxn<<2],setv[maxn<<2];
int minv[maxn<<2];
void build(int o,int l,int r)
{
setv[o]=maxv[o]=minv[o]=0;
if(l==r)
return ;
int mid=(l+r)>>1;
build(o<<1,l,mid);
build(o<<1|1,mid+1,r);
}
void pushup(int o)
{
maxv[o]=max(maxv[o<<1],maxv[o<<1|1]);
minv[o]=min(minv[o<<1],minv[o<<1|1]);
}
void maintain(int o)
{
swap(minv[o],maxv[o]);
minv[o]=-minv[o];
maxv[o]=-maxv[o];
}
void pushdown(int o)
{
if(setv[o])
{
maintain(o<<1);
maintain(o<<1|1);
setv[o<<1]^=1;//注意要是异或
setv[o<<1|1]^=1;
setv[o]=0;
}
}
void update1(int o,int l,int r,int x,int val)
{
if(l==r)
{
minv[o]=maxv[o]=val;
setv[o]=0;
return;
}
pushdown(o);
int mid=(l+r)>>1;
if(x<=mid)update1(o<<1,l,mid,x,val);
else update1(o<<1|1,mid+1,r,x,val);
pushup(o);
}
void update2(int o,int l,int r,int q1,int q2)
{
if(q1<=l&&r<=q2)
{
maintain(o);
setv[o]^=1;
return ;
}
pushdown(o);
int mid=(l+r)>>1;
if(q1<=mid)update2(o<<1,l,mid,q1,q2);
if(q2>mid)update2(o<<1|1,mid+1,r,q1,q2);
pushup(o);
}
int query(int o,int l,int r,int q1,int q2)
{
if(q1<=l&&r<=q2)return maxv[o];
pushdown(o);
int mid=(l+r)>>1;
int ans=-INF;
if(q1<=mid)ans=max(ans,query(o<<1,l,mid,q1,q2));
if(q2>mid)ans=max(ans,query(o<<1|1,mid+1,r,q1,q2));
pushup(o);
return ans;
}
}tree;
void Negate(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);
}
tree.update2(1,0,pos-1,w[f1],w[u]);
u=fa[f1],f1=top[u];
}
if(u==v)return;
if(deep[u]>deep[v])swap(u,v);
tree.update2(1,0,pos-1,w[son[u]],w[v]);
}
int Query(int u,int v)
{
int f1=top[u],f2=top[v];
int ans=-INF;
while(f1!=f2)
{
if(deep[f1]<deep[f2])
{
swap(f1,f2);
swap(u,v);
}
ans=max(ans,tree.query(1,0,pos-1,w[f1],w[u]));
u=fa[f1],f1=top[u];
}
if(u==v)return ans;
if(deep[u]>deep[v])swap(u,v);
ans=max(ans,tree.query(1,0,pos-1,w[son[u]],w[v]));
return ans;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d",&N);
init();
for(int i=0;i<N-1;i++)
{
scanf("%d%d%d",&e[i].a,&e[i].b,&e[i].w);
add_edge(e[i].a,e[i].b);
add_edge(e[i].b,e[i].a);
}
dfs1(1,0,0);
dfs2(1,1);
tree.build(1,0,pos-1);
char op[10];
for(int i=0;i<N-1;i++)
{
if(deep[e[i].a]>deep[e[i].b])
swap(e[i].a,e[i].b);
tree.update1(1,0,pos-1,w[e[i].b],e[i].w);
}
int x,y;
while(scanf("%s",op)!=EOF)
{
if(op[0]=='D')break;
scanf("%d%d",&x,&y);
if(op[0]=='C')
tree.update1(1,0,pos-1,w[e[x-1].b],y);
else if(op[0]=='N')
Negate(x,y);
else printf("%d\n",Query(x,y));
}
}
return 0;
}