Description
Ray 乐忠于旅游,这次他来到了T 城。T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接。为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路径。换句话说, T 城中只有N − 1 座桥。Ray 发现,有些桥上可以看到美丽的景色,让人心情愉悦,但有些桥狭窄泥泞,令人烦躁。于是,他给每座桥定义一个愉悦度w,也就是说,Ray 经过这座桥会增加w 的愉悦度,这或许是正的也可能是负的。有时,Ray 看待同一座桥的心情也会发生改变。现在,Ray 想让你帮他计算从u 景点到v 景点能获得的总愉悦度。有时,他还想知道某段路上最美丽的桥所提供的最大愉悦度,或是某段路上最糟糕的一座桥提供的最低愉悦度。
Input
输入的第一行包含一个整数N,表示T 城中的景点个数。景点编号为 0…N − 1。接下来N − 1 行,每行三个整数u、v 和w,表示有一条u 到v,使 Ray 愉悦度增加w 的桥。桥的编号为1…N − 1。|w| <= 1000。输入的第N + 1 行包含一个整数M,表示Ray 的操作数目。接下来有M 行,每行描述了一个操作,操作有如下五种形式: C i w,表示Ray 对于经过第i 座桥的愉悦度变成了w。 N u v,表示Ray 对于经过景点u 到v 的路径上的每一座桥的愉悦度都变成原来的相反数。 SUM u v,表示询问从景点u 到v 所获得的总愉悦度。 MAX u v,表示询问从景点u 到v 的路径上的所有桥中某一座桥所提供的最大愉悦度。 MIN u v,表示询问从景点u 到v 的路径上的所有桥中某一座桥所提供的最小愉悦度。测试数据保证,任意时刻,Ray 对于经过每一座桥的愉悦度的绝对值小于等于1000。
Output
对于每一个询问(操作S、MAX 和MIN),输出答案。
Sample Input
3
0 1 1
1 2 2
8
SUM 0 2
MAX 0 2
N 0 1
SUM 0 2
MIN 0 2
C 1 3
SUM 0 2
MAX 0 2
Sample Output
3
2
1
-1
5
3
HINT
一共有10 个数据,对于第i (1 <= i <= 10) 个数据, N = M = i * 2000。
思路
一个裸的树链剖分,支持边的修改,途径路径最大值,途径路径最小值,路径权值和
首先一遍dfs求每个点的父亲节点和每个点儿子中权值最大的重链
然后一遍dfs进行每条边重新编号
然后维护一下线段树就好了
注意:还有线段树维护时一定不要像以前一样直接建完全二叉树,那样会存不下,导致RE
注意:那个lazy值在用后一定要更新,我就因为没更新,T了一篇
说多了都是泪呀…
代码
#include <bits/stdc++.h>
#define N 100050
using namespace std;
struct edge{int v,w,nxt;}a[N<<2];
struct edge_{int u,v,w;}a_[N<<2];
struct pppp{int sum,mi,ma,lazy;}tr[N<<2];
int n,m,he[N],f[N],siz[N],top[N],dis[N],cnt=0,tot=0;
int c[N],ls[N<<2],rs[N<<2];
int root,pp=0,pp_=0,w[N],son[N];
inline void add(int x,int y,int z){
a[++pp].v=y;a[pp].w=z;a[pp].nxt=he[x];he[x]=pp;
a[++pp].v=x;a[pp].w=z;a[pp].nxt=he[y];he[y]=pp;
}
inline void add_(int u,int v,int w){
a_[++pp_].u=u;
a_[pp_].v=v;
a_[pp_].w=w;
}
void dfs1(int x,int father){
siz[x]=1;son[x]=0;
for(int i=he[x];i;i=a[i].nxt){
int v=a[i].v;
if(v!=father){
f[v]=x;dis[v]=dis[x]+1;
dfs1(v,x);
siz[x]+=siz[v];
if(siz[v]>siz[son[x]])son[x]=v;
}
}
}
void dfs2(int x,int father){
top[x]=father;w[x]=++cnt;
if(son[x]!=0)dfs2(son[x],father);
for(int i=he[x];i;i=a[i].nxt){
int v=a[i].v;
if(v!=f[x]){
if(v!=son[x])dfs2(v,v);
c[w[v]]=a[i].w;
}
}
}
void pushup(int rt){
tr[rt].sum=tr[ls[rt]].sum+tr[rs[rt]].sum;
tr[rt].ma=max(tr[ls[rt]].ma,tr[rs[rt]].ma);
tr[rt].mi=min(tr[ls[rt]].mi,tr[rs[rt]].mi);
}
void build(int &rt,int l,int r){
rt=++tot;tr[rt].lazy=0;
if(l==r){tr[rt].sum=tr[rt].mi=tr[rt].ma=c[l];return ;}
int mid=(l+r)>>1;
build(ls[rt],l,mid);
build(rs[rt],mid+1,r);
pushup(rt);
}
void pushdown(int rt){
int r1,r2;
if(tr[rt].lazy==1){
tr[ls[rt]].sum=-tr[ls[rt]].sum;tr[rs[rt]].sum=-tr[rs[rt]].sum;
r1=tr[ls[rt]].mi;r2=tr[ls[rt]].ma;tr[ls[rt]].mi=-r2;tr[ls[rt]].ma=-r1;
r1=tr[rs[rt]].mi;r2=tr[rs[rt]].ma;tr[rs[rt]].mi=-r2;tr[rs[rt]].ma=-r1;
tr[ls[rt]].lazy^=1;tr[rs[rt]].lazy^=1;
tr[rt].lazy=0;
}
}
void modify(int rt,int left,int right,int l,int r,int p,int type){
pushdown(rt);
if((left==l)&&(right==r)){
if(type==1){
tr[rt].sum=p;
tr[rt].ma=p;tr[rt].mi=p;
return;
}
else{
tr[rt].lazy^=1;
tr[rt].sum=-tr[rt].sum;
int r1,r2;r1=tr[rt].mi;r2=tr[rt].ma;
tr[rt].mi=-r2;tr[rt].ma=-r1;
return;
}
}
int mid=(left+right)>>1;
if(r<=mid)modify(ls[rt],left,mid,l,r,p,type);
else if(l>=mid+1)modify(rs[rt],mid+1,right,l,r,p,type);
else{
modify(ls[rt],left,mid,l,mid,p,type);
modify(rs[rt],mid+1,right,mid+1,r,p,type);
}
pushup(rt);
}
int ask(int rt,int left,int right,int l,int r,int type){
pushdown(rt);
if((left==l)&&(right==r)){
if(type==1)return tr[rt].sum;
else if(type==2)return tr[rt].ma;
else return tr[rt].mi;
}
int mid=(left+right)>>1;
if(r<=mid)return ask(ls[rt],left,mid,l,r,type);
else if(l>=mid+1)return ask(rs[rt],mid+1,right,l,r,type);
else{
if(type==1)return ask(ls[rt],left,mid,l,mid,type)+ask(rs[rt],mid+1,right,mid+1,r,type);
else if(type==2)return max(ask(ls[rt],left,mid,l,mid,type),ask(rs[rt],mid+1,right,mid+1,r,type));
else return min(ask(ls[rt],left,mid,l,mid,type),ask(rs[rt],mid+1,right,mid+1,r,type));
}
}char s[10];
int main(){
scanf("%d",&n);int x,y,z;
for(int i=1;i<n;++i){
scanf("%d%d%d",&x,&y,&z);
++x;++y;
add(x,y,z);add_(x,y,z);
}
dfs1(1,1);dfs2(1,1);
build(root,1,cnt);
scanf("%d",&m);int u,v;
for(int i=1;i<=m;++i){
scanf("%s",s);scanf("%d%d",&x,&y);
if(s[0]=='C'){
u=a_[x].u;v=a_[x].v;
if(f[u]==v)modify(root,1,cnt,w[u],w[u],y,1);
else modify(root,1,cnt,w[v],w[v],y,1);
}
else{
x++;y++;
int f1=top[x],f2=top[y];
if(s[0]=='N'){
while(f1!=f2){
if(dis[f1]<dis[f2]){swap(f1,f2);swap(x,y);}
modify(root,1,cnt,w[f1],w[x],0,2);
x=f[f1];f1=top[x];
}
if(x!=y){
if(dis[x]>dis[y])swap(x,y);
modify(root,1,cnt,w[son[x]],w[y],0,2);
}
}
else if(s[0]=='S'){
int ans=0;
while(f1!=f2){
if(dis[f1]<dis[f2]){swap(f1,f2);swap(x,y);}
ans+=ask(root,1,cnt,w[f1],w[x],1);
x=f[f1];f1=top[x];
}
if(x!=y){
if(dis[x]>dis[y])swap(x,y);
ans+=ask(root,1,cnt,w[son[x]],w[y],1);
}
printf("%d\n",ans);
}
else if((s[0]=='M')&&(s[1]=='A')){
int ans=0xefefefef;
while(f1!=f2){
if (dis[f1]<dis[f2]) {swap(f1,f2);swap(x,y);}
ans=max(ans,ask(root,1,cnt,w[f1],w[x],2));
x=f[f1];f1=top[x];
}
if(x!=y){
if(dis[x]>dis[y])swap(x,y);
ans=max(ans,ask(root,1,cnt,w[son[x]],w[y],2));
}
printf("%d\n",ans);
}
else{
int ans=0x3f3f3f3f;
while(f1!=f2){
if(dis[f1]<dis[f2]){swap(f1,f2);swap(x,y);}
ans=min(ans,ask(root,1,cnt,w[f1],w[x],3));
x=f[f1];f1=top[x];
}
if(x!=y){
if(dis[x]>dis[y])swap(x,y);
ans=min(ans,ask(root,1,cnt,w[son[x]],w[y],3));
}
printf("%d\n",ans);
}
}
}
return 0;
}