Time Limit: 5000MS | Memory Limit: 131072K | |
Total Submissions: 11539 | Accepted: 2977 |
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
题意:给出n-1条双向边,每个边有权值
有三种操作:
1.改变第i条边的边权为w
2.对u到v路径上的边权值取反
3.查询u到v路径上的最大边的边权
开始做树链剖分的第一题,树链剖分代码太长了,有很多细节需要注意
首先是建树,由于这里查询的是边,于是需要用边建树,其实和用点建树没什么区别,只需要把边权放在深度较大的那个点上即可
操作1:直接线段树单点更新维护
操作2:对于求u到v路径上最大边权,由于有取反操作,那么在线段树维护最大值时需要同时维护最大值和最小值,在取反的时候最小值就变成了最大值,最大值变成了最小值,这样就可以O(1)维护最值
操作3:查询
另外还要注意,在更新和查询的时候,如果在同一条重链上,更新深度较低的那点的重儿子到深度较高的那点即可(因为边权都放在了深度较高的点上,如果此时还更新了最上边那个点就多更新了一条边)
还有很多小细节,比如最大值可能为负,所以ans的初值需要定义为 -inf,具体看代码把
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cassert>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
const int N=1e5+10;
const int M=(N<<2);
typedef long long ll;
ll siz[N],top[N],son[N],dep[N],faz[N],tid[N],rnk[N];
ll a[N],first[N],cnt,n,tot;
struct node
{
ll l,r,minn,maxx,lazy;
ll mid()
{
return (l+r)>>1;
}
}t[N<<2];
struct edge
{
ll v,w,next;
}e[N<<1];
void dfs1(ll u,ll father,ll depth)
{
dep[u]=depth;
faz[u]=father;
siz[u]=1;
for(ll i=first[u];~i;i=e[i].next)
{
ll v=e[i].v;
if(v!=father)
{
a[v]=e[i].w;
dfs1(v,u,depth+1);
siz[u]+=siz[v];
if(son[u]==-1||siz[v]>siz[son[u]])
son[u]=v;
}
}
}
void dfs2(ll u,ll t)
{
top[u]=t;
tid[u]=++cnt;
rnk[cnt]=u;
if(son[u]==-1)return;
dfs2(son[u],t);
for(ll i=first[u];~i;i=e[i].next)
{
ll v=e[i].v;
if(v!=son[u]&&v!=faz[u])
dfs2(v,v);
}
}
void pushup(ll rt)
{
t[rt].maxx=max(t[rt<<1].maxx,t[rt<<1|1].maxx);
t[rt].minn=min(t[rt<<1].minn,t[rt<<1|1].minn);
}
void nega(ll rt)
{
t[rt].lazy^=1;
swap(t[rt].maxx,t[rt].minn);
t[rt].maxx*=-1;
t[rt].minn*=-1;
}
void pushdown(ll rt)
{
if(t[rt].lazy)
{
nega(rt<<1);
nega(rt<<1|1);
t[rt].lazy=0;
}
}
void build(ll l,ll r,ll rt)
{
t[rt].l=l,t[rt].r=r,t[rt].lazy=0;
if(l==r)
{
t[rt].minn=t[rt].maxx=a[rnk[l]];
return;
}
ll m=(l+r)>>1;
build(l,m,rt<<1);
build(m+1,r,rt<<1|1);
pushup(rt);
}
void update(ll ql,ll qr,ll rt)
{
if(ql<=t[rt].l&&t[rt].r<=qr)
{
nega(rt);
return;
}
pushdown(rt);
ll m=t[rt].mid();
if(ql<=m)update(ql,qr,rt<<1);
if(qr>m)update(ql,qr,rt<<1|1);
pushup(rt);
}
void change(ll q,ll rt,ll w)
{
if(t[rt].l==t[rt].r)
{
t[rt].maxx=t[rt].minn=w;
return;
}
pushdown(rt);
ll m=t[rt].mid();
if(q<=m)
change(q,rt<<1,w);
else
change(q,rt<<1|1,w);
pushup(rt);
}
ll query(ll ql,ll qr,ll rt)
{
if(ql<=t[rt].l&&t[rt].r<=qr)
return t[rt].maxx;
pushdown(rt);
ll m=t[rt].mid();
ll ans=-1e18;
if(ql<=m)ans=max(ans,query(ql,qr,rt<<1));
if(qr>m)ans=max(ans,query(ql,qr,rt<<1|1));
return ans;
}
ll query_path(ll x,ll y)
{
ll ans=-1e18;
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
ans=max(ans,query(tid[top[x]],tid[x],1));
x=faz[top[x]];
}
if(x!=y)
{
if(tid[x]>tid[y])swap(x,y);
ans=max(ans,query(tid[son[x]],tid[y],1));
}
return ans;
}
void update_path(ll x,ll y)
{
while(top[x]!=top[y])
{
if(dep[top[x]]<dep[top[y]])swap(x,y);
update(tid[top[x]],tid[x],1);
x=faz[top[x]];
}
if(x!=y)
{
if(tid[x]>tid[y])swap(x,y);
update(tid[son[x]],tid[y],1);
}
}
void init()
{
mem(son,-1);
mem(first,-1);
tot=cnt=0;
}
void add(ll u,ll v,ll w)
{
e[tot].v=v;
e[tot].w=w;
e[tot].next=first[u];
first[u]=tot++;
}
int main()
{
ll t,u,v,w,x,y;
char op[10];
scanf("%lld",&t);
while(t--)
{
scanf("%lld",&n);
init();
for(ll i=2; i<=n; i++)
{
scanf("%lld%lld%lld",&u,&v,&w);
add(u,v,w);
add(v,u,w);
}
dfs1(1,1,1);
dfs2(1,1);
build(1,n,1);
while(scanf("%s",op)&&op[0]!='D')
{
scanf("%lld%lld",&x,&y);
if(op[0]=='C')
{
ll now=x*2-1;
u=tid[e[now].v]>tid[e[now^1].v]?tid[e[now].v]:tid[e[now^1].v];
change(u,1,y);
}
else if(op[0]=='N')
update_path(x,y);
else
printf("%lld\n",query_path(x,y));
}
}
return 0;
}