Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 3405 | Accepted: 953 |
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
Source
题意:给定一棵树,有3个操作:1、修改某条边权值。2、询问2个节点间最大边权。3、把2个节点间所有边权取相反数
题解:树链剖分。。线段树部分需要lazy。。还挺好写的,不过要注意一下lazy值的维护
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
const int maxn = 100008;
struct edge{
int to,next;
}e[maxn<<1];
struct segment{
int ma,mi,lazy;
}tree[maxn<<2];
int head[maxn],d[maxn][3];
int dep[maxn],w[maxn],fa[maxn];
int top[maxn],son[maxn],siz[maxn];
int n,all,root,t,a,b,c,z;
char s[18];
void add(int x,int y)
{
e[++all].to=y;
e[all].next=head[x];
head[x]=all;
}
void dfs(int x)
{
siz[x]=1; son[x]=0;
for(int i=head[x];i!=-1;i=e[i].next)
{
if(e[i].to==fa[x]) continue;
fa[e[i].to]=x;
dep[e[i].to]=dep[x]+1;
dfs(e[i].to);
if(siz[e[i].to]>siz[son[x]]) son[x]=e[i].to;
siz[x]+=siz[e[i].to];
}
}
void build_tree(int x,int tp)
{
w[x]=++z; top[x]=tp;
if(son[x]!=0) build_tree(son[x],top[x]);
for(int i=head[x];i!=-1;i=e[i].next)
{
if(e[i].to!=son[x]&&e[i].to!=fa[x])
build_tree(e[i].to,e[i].to);
}
}
void build_segment_tree(int pos,int l,int r)
{
int mid=(l+r)>>1,ls=pos<<1,rs=pos<<1|1;
tree[pos].lazy=0;
tree[pos].ma=-0xffffff;
tree[pos].mi=0xffffff;
if(l==r) return;
build_segment_tree(ls,l,mid);
build_segment_tree(rs,mid+1,r);
}
void make_negate(int pos)
{
tree[pos].ma=-tree[pos].ma;
tree[pos].mi=-tree[pos].mi;
swap(tree[pos].ma,tree[pos].mi);
}
void push_down(int pos)
{
int ls=pos<<1,rs=pos<<1|1;
tree[pos].lazy=0;
tree[ls].lazy^=1;
tree[rs].lazy^=1;
make_negate(ls);
make_negate(rs);
}
void push_up(int pos)
{
tree[pos].ma=max(tree[pos<<1].ma,tree[pos<<1|1].ma);
tree[pos].mi=min(tree[pos<<1].mi,tree[pos<<1|1].mi);
}
void update(int pos,int l,int r,int loc,int val)
{
int mid=(l+r)>>1,ls=pos<<1,rs=pos<<1|1;
if(loc>r||loc<l) return;
if(l==r){ tree[pos].mi=tree[pos].ma=val; return; }
if(tree[pos].lazy) push_down(pos);
update(ls,l,mid,loc,val);
update(rs,mid+1,r,loc,val);
push_up(pos);
}
int maxi(int pos,int l,int r,int ltemp,int rtemp)
{
int mid=(l+r)>>1,ls=pos<<1,rs=pos<<1|1;
if(l>rtemp||ltemp>r) return -0xffffff;
if(ltemp<=l&&r<=rtemp) return tree[pos].ma;
if(tree[pos].lazy) push_down(pos);
return max(maxi(ls,l,mid,ltemp,rtemp)
,maxi(rs,mid+1,r,ltemp,rtemp));
}
int myfind(int va,int vb)
{
int f1=top[va],f2=top[vb],tmp=-0xffffff;
while(f1!=f2)
{
if(dep[f1]<dep[f2]){ swap(f1,f2); swap(va,vb); }
tmp=max(tmp,maxi(1,1,z,w[f1],w[va]));
va=fa[f1]; f1=top[va];
}
if(va==vb) return tmp;
if(dep[va]>dep[vb]) swap(va,vb);
return max(tmp,maxi(1,1,z,w[son[va]],w[vb]));
}
void update_negate(int pos,int l,int r,int ltemp,int rtemp)
{
int mid=(l+r)>>1,ls=pos<<1,rs=pos<<1|1;
if(l>rtemp||ltemp>r) return;
//printf("cc %d %d %d %d\n",l,r,ltemp,rtemp);
if(ltemp<=l&&r<=rtemp)
{
tree[pos].lazy^=1;
make_negate(pos);
return;
}
if(tree[pos].lazy) push_down(pos);
update_negate(ls,l,mid,ltemp,rtemp);
update_negate(rs,mid+1,r,ltemp,rtemp);
push_up(pos);
}
void mynegate(int va,int vb)
{
int f1=top[va],f2=top[vb];
while(f1!=f2)
{
if(dep[f1]<dep[f2]){ swap(f1,f2); swap(va,vb); }
update_negate(1,1,z,w[f1],w[va]);
va=fa[f1]; f1=top[va];
}
if(va==vb) return;
if(dep[va]>dep[vb]) swap(va,vb);
update_negate(1,1,z,w[son[va]],w[vb]);
}
int main()
{
scanf("%d",&t);
while(t--)
{
memset(head,-1,sizeof(head));
memset(tree,0,sizeof(tree));
memset(siz,0,sizeof(siz));
scanf("%d",&n);
root=(n+1)/2;
fa[root]=dep[root]=z=all=0;
for(int i=1;i<n;i++)
{
scanf("%d%d%d",&a,&b,&c);
d[i][0]=a,d[i][1]=b,d[i][2]=c;
add(a,b),add(b,a);
}
dfs(root);
build_tree(root,root);
build_segment_tree(1,1,z);
for(int i=1;i<n;i++)
{
if(dep[d[i][0]]>dep[d[i][1]]) swap(d[i][0],d[i][1]);
update(1,1,z,w[d[i][1]],d[i][2]);
}
while(scanf("%s",s),s[0]!='D')
{
scanf("%d%d",&a,&b);
if(s[0]=='Q') printf("%d\n",myfind(a,b));
else if(s[0]=='N') mynegate(a,b);
else update(1,1,z,w[d[a][1]],b);
}
}
return 0;
}