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),输出答案。
树链剖分裸题,操作都挺常规的,变相反数只要搞个标记就好了。只不过我实在太弱了(以后要记得及时下传标记啊!),写得很长……不过大部分都是复制粘贴的,所以其实也挺好写的,不要怕……
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int maxn=20005;
const int inf=999999999;
struct edge{int x,y,d,next;}e[maxn*5],E[maxn*5];
struct xdtree{int l,r,lc,rc,mx,mn,sum;bool ff;}a[maxn*10];
int tot[maxn],dep[maxn],ys[maxn],Num=0,top[maxn],son[maxn],fa[maxn];
int last[maxn],len=0;
int n,q;
void ins(int x,int y,int d)
{
int t=++len;
e[t].y=y;e[t].d=d;e[t].next=last[x];last[x]=t;
}
void work1(int x,int Fa)
{
son[x]=0;tot[x]=1;dep[x]=dep[Fa]+1;fa[x]=Fa;
for(int i=last[x];i!=-1;i=e[i].next)
{
int y=e[i].y;
if(y==Fa) continue;
work1(y,x);
tot[x]+=tot[y];
if(tot[son[x]]<tot[y]) son[x]=y;
}
}
void work2(int x,int t)
{
ys[x]=++Num;top[x]=t;
if(son[x]!=0) work2(son[x],t);
for(int i=last[x];i!=-1;i=e[i].next)
{
int y=e[i].y;
if(y==son[x] || y==fa[x]) continue;
work2(y,y);
}
}
int trlen=0;
void build(int l,int r)
{
int t=++trlen;
a[t].l=l;a[t].r=r;a[t].sum=0;a[t].mx=-inf;a[t].mn=inf;a[t].ff=false;
if(l<r)
{
int mid=l+r>>1;
a[t].lc=trlen+1;build(l,mid);
a[t].rc=trlen+1;build(mid+1,r);
}
}
void change1(int now,int l,int r)
{
if(a[now].l==l && a[now].r==r)
{
a[now].ff=!a[now].ff;
a[now].sum*=-1;
int Mx=a[now].mx,Mn=a[now].mn;
a[now].mx=-Mn;a[now].mn=-Mx;
return;
}
int lc=a[now].lc,rc=a[now].rc,mid=a[now].l+a[now].r>>1;
if(a[now].ff==true)
{
a[now].ff=false;
a[lc].ff=!a[lc].ff;a[rc].ff=!a[rc].ff;
int Mx,Mn;
Mx=a[lc].mx;Mn=a[lc].mn;
a[lc].mx=-Mn;a[lc].mn=-Mx;a[lc].sum*=-1;
Mx=a[rc].mx;Mn=a[rc].mn;
a[rc].mx=-Mn;a[rc].mn=-Mx;a[rc].sum*=-1;
}
if(r<=mid) change1(lc,l,r);
else if(l>mid) change1(rc,l,r);
else change1(lc,l,mid),change1(rc,mid+1,r);
a[now].sum=a[lc].sum+a[rc].sum;
a[now].mx=max(a[lc].mx,a[rc].mx);
a[now].mn=min(a[lc].mn,a[rc].mn);
}
void change(int now,int x,int k)
{
if(a[now].l==a[now].r)
{
a[now].mx=a[now].mn=a[now].sum=k;
return;
}
int mid=a[now].l+a[now].r>>1,lc=a[now].lc,rc=a[now].rc;
if(a[now].ff==true)
{
a[now].ff=false;
a[lc].ff=!a[lc].ff;a[rc].ff=!a[rc].ff;
int Mx,Mn;
Mx=a[lc].mx;Mn=a[lc].mn;
a[lc].mx=-Mn;a[lc].mn=-Mx;a[lc].sum*=-1;
Mx=a[rc].mx;Mn=a[rc].mn;
a[rc].mx=-Mn;a[rc].mn=-Mx;a[rc].sum*=-1;
}
if(x<=mid) change(lc,x,k);
else change(rc,x,k);
a[now].sum=a[lc].sum+a[rc].sum;
a[now].mx=max(a[lc].mx,a[rc].mx);
a[now].mn=min(a[lc].mn,a[rc].mn);
}
int findmx(int now,int l,int r)
{
if(a[now].l==l && a[now].r==r) return a[now].mx;
int mid=a[now].l+a[now].r>>1,lc=a[now].lc,rc=a[now].rc;
if(a[now].ff==true)
{
a[now].ff=false;
a[lc].ff=!a[lc].ff;a[rc].ff=!a[rc].ff;
int Mx,Mn;
Mx=a[lc].mx;Mn=a[lc].mn;
a[lc].mx=-Mn;a[lc].mn=-Mx;a[lc].sum*=-1;
Mx=a[rc].mx;Mn=a[rc].mn;
a[rc].mx=-Mn;a[rc].mn=-Mx;a[rc].sum*=-1;
}
if(r<=mid) return findmx(lc,l,r);
else if(l>mid) return findmx(rc,l,r);
else return max(findmx(lc,l,mid),findmx(rc,mid+1,r));
}
int findmn(int now,int l,int r)
{
if(a[now].l==l && a[now].r==r) return a[now].mn;
int mid=a[now].l+a[now].r>>1,lc=a[now].lc,rc=a[now].rc;
if(a[now].ff==true)
{
//printf("ok\n");
a[now].ff=false;
a[lc].ff=!a[lc].ff;a[rc].ff=!a[rc].ff;
int Mx,Mn;
Mx=a[lc].mx;Mn=a[lc].mn;
a[lc].mx=-Mn;a[lc].mn=-Mx;a[lc].sum*=-1;
Mx=a[rc].mx;Mn=a[rc].mn;
a[rc].mx=-Mn;a[rc].mn=-Mx;a[rc].sum*=-1;
}
if(r<=mid) return findmn(lc,l,r);
else if(l>mid) return findmn(rc,l,r);
else return min(findmn(lc,l,mid),findmn(rc,mid+1,r));
}
int getsum(int now,int l,int r)
{
if(a[now].l==l && a[now].r==r) return a[now].sum;
int mid=a[now].l+a[now].r>>1,lc=a[now].lc,rc=a[now].rc;
if(a[now].ff==true)
{
//printf("ok\n");
a[now].ff=false;
a[lc].ff=!a[lc].ff;a[rc].ff=!a[rc].ff;
int Mx,Mn;
Mx=a[lc].mx;Mn=a[lc].mn;
a[lc].mx=-Mn;a[lc].mn=-Mx;a[lc].sum*=-1;
Mx=a[rc].mx;Mn=a[rc].mn;
a[rc].mx=-Mn;a[rc].mn=-Mx;a[rc].sum*=-1;
}
if(r<=mid) return getsum(lc,l,r);
else if(l>mid) return getsum(rc,l,r);
else return getsum(lc,l,mid)+getsum(rc,mid+1,r);
}
int smx(int x,int y)
{
int tx=top[x],ty=top[y],ans=-inf;
while(tx!=ty)
{
if(dep[tx]>dep[ty]) swap(tx,ty),swap(x,y);
ans=max(ans,findmx(1,ys[ty],ys[y]));
y=fa[ty];ty=top[y];
}
if(x==y) return ans;
else
{
if(dep[x]>dep[y]) swap(x,y);
return max(ans,findmx(1,ys[son[x]],ys[y]));
}
}
int smn(int x,int y)
{
int tx=top[x],ty=top[y],ans=inf;
while(tx!=ty)
{
if(dep[tx]>dep[ty]) swap(tx,ty),swap(x,y);
ans=min(ans,findmn(1,ys[ty],ys[y]));
y=fa[ty];ty=top[y];
}
if(x==y) return ans;
else
{
if(dep[x]>dep[y]) swap(x,y);
return min(ans,findmn(1,ys[son[x]],ys[y]));
}
}
int gsum(int x,int y)
{
int tx=top[x],ty=top[y],ans=0;
while(tx!=ty)
{
if(dep[tx]>dep[ty]) swap(tx,ty),swap(x,y);
ans+=getsum(1,ys[ty],ys[y]);
y=fa[ty];ty=top[y];
}
if(x==y) return ans;
else
{
if(dep[x]>dep[y]) swap(x,y);
return ans+getsum(1,ys[son[x]],ys[y]);
}
}
void Change(int x,int y)
{
int tx=top[x],ty=top[y];
while(tx!=ty)
{
if(dep[tx]>dep[ty]) swap(tx,ty),swap(x,y);
change1(1,ys[ty],ys[y]);
//printf("%d %d\n",ys[ty],ys[y]);
y=fa[ty];ty=top[y];
}
if(x!=y)
{
if(dep[x]>dep[y]) swap(x,y);
change1(1,ys[son[x]],ys[y]);
//printf("%d %d\n",ys[son[x]],ys[y]);
}
}
int main()
{
memset(last,-1,sizeof(last));
scanf("%d",&n);
for(int i=1;i<n;i++)
{
int x,y,d;
scanf("%d%d%d",&x,&y,&d);x++;y++;
E[i].x=x;E[i].y=y;E[i].d=d;
ins(x,y,d);ins(y,x,d);
}
scanf("%d",&q);
dep[1]=0;work1(1,0);
work2(1,1);
build(1,Num);
for(int i=1;i<n;i++)
{
if(dep[E[i].x]>dep[E[i].y]) swap(E[i].x,E[i].y);
change(1,ys[E[i].y],E[i].d);
}
//for(int i=1;i<=trlen;i++) printf("%d %d %d %d %d %d\n",i,a[i].l,a[i].r,a[i].mx,a[i].mn,a[i].sum);
for(int i=1;i<=q;i++)
{
char oo[10];
int x,y;
scanf("%s%d%d",oo,&x,&y);
if(oo[0]=='C') change(1,ys[E[x].y],y);
else if(oo[0]=='N') Change(x+1,y+1);
else if(oo[0]=='S') printf("%d\n",gsum(x+1,y+1));
else if(oo[1]=='A') printf("%d\n",smx(x+1,y+1));
else printf("%d\n",smn(x+1,y+1));
}
}