[国家集训队]旅游
题目描述
Ray 乐忠于旅游,这次他来到了T 城。T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥连接。为了方便游客到达每个景点但又为了节约成本,T 城的任意两个景点之间有且只有一条路径。换句话说, T 城中只有N − 1 座桥。
Ray 发现,有些桥上可以看到美丽的景色,让人心情愉悦,但有些桥狭窄泥泞,令人烦躁。于是,他给每座桥定义一个愉悦度w,也就是说,Ray 经过这座桥会增加w 的愉悦度,这或许是正的也可能是负的。有时,Ray 看待同一座桥的心情也会发生改变。
现在,Ray 想让你帮他计算从u 景点到v 景点能获得的总愉悦度。有时,他还想知道某段路上最美丽的桥所提供的最大愉悦度,或是某段路上最糟糕的一座桥提供的最低愉悦度。
输入格式
输入的第一行包含一个整数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。
输出格式
对于每一个询问(操作S、MAX 和MIN),输出答案。
是道水题,但好麻烦啊
注意释放取反标记时最大值的相反数是释放后最小值
同理
#include<bits/stdc++.h> #define re return #define inc(i,l,r) for(int i=l;i<=r;++i) using namespace std; template<typename T>inline void rd(T&x) { char c;bool f=0; while((c=getchar())<'0'||c>'9')if(c=='-')f=1; x=c^48; while((c=getchar())>='0'&&c<='9')x=x*10+(c^48); if(f)x=-x; } const int maxn=500005; int n,m,tot,k=1,hd[maxn],val[maxn],ans; int size[maxn],deep[maxn],fa[maxn],son[maxn]; int top[maxn],rev[maxn],sub[maxn]; struct node{ int to,nt,val; }e[maxn<<1]; inline void add(int x,int y,int val) { e[++k].to=y;e[k].nt=hd[x];hd[x]=k;e[k].val=val; e[++k].to=x;e[k].nt=hd[y];hd[y]=k;e[k].val=val; } inline void dfs1(int x) { deep[x]=deep[fa[x]]+1; size[x]=1; for(int i=hd[x];i;i=e[i].nt) { int v=e[i].to; if(!fa[v]) { fa[v]=x; dfs1(v); val[v]=e[i].val; size[x]+=size[v]; if(size[v]>size[son[x]])son[x]=v; } } } inline void dfs2(int x,int topf) { top[x]=topf; sub[x]=++tot; rev[tot]=x; if(son[x]) dfs2(son[x],topf); for(int i=hd[x];i;i=e[i].nt) { int v=e[i].to; if(!top[v]) dfs2(v,v); } } #define ls rt<<1 #define rs rt<<1|1 int maxx[maxn<<2],lazy[maxn<<2],sum[maxn<<2],minn[maxn<<2]; inline void pushup(int rt) { sum[rt]=sum[ls]+sum[rs]; maxx[rt]=max(maxx[ls],maxx[rs]); minn[rt]=min(minn[ls],minn[rs]); } inline void build(int rt,int l,int r) { if(l==r) { maxx[rt]=minn[rt]=sum[rt]=val[rev[l]]; re ; } int mid=(l+r)>>1; build(ls,l,mid); build(rs,mid+1,r); pushup(rt); } inline void pushdown(int rt) { lazy[ls]^=1;lazy[rs]^=1; sum[ls]=-sum[ls];sum[rs]=-sum[rs]; maxx[ls]^=minn[ls]^=maxx[ls]^=minn[ls]; maxx[rs]^=minn[rs]^=maxx[rs]^=minn[rs]; maxx[ls]=-maxx[ls];maxx[rs]=-maxx[rs]; minn[ls]=-minn[ls];minn[rs]=-minn[rs]; lazy[rt]^=1; } inline void change(int rt,int l,int r,int x,int add) { if(l==r) { sum[rt]=maxx[rt]=minn[rt]=add; re ; } if(lazy[rt])pushdown(rt); int mid=(l+r)>>1; if(x<=mid)change(ls,l,mid,x,add); else change(rs,mid+1,r,x,add); pushup(rt); } inline void reverse(int rt,int l,int r,int x,int y) { if(x<=l&&r<=y) { sum[rt]=-sum[rt]; maxx[rt]^=minn[rt]^=maxx[rt]^=minn[rt]; maxx[rt]=-maxx[rt];minn[rt]=-minn[rt]; lazy[rt]^=1; re ; } if(lazy[rt])pushdown(rt); int mid=(l+r)>>1; if(x<=mid)reverse(ls,l,mid,x,y); if(y>mid)reverse(rs,mid+1,r,x,y); pushup(rt); } inline void SUM(int rt,int l,int r,int x,int y) { if(x<=l&&r<=y) { ans+=sum[rt]; re ; } if(lazy[rt])pushdown(rt); int mid=(l+r)>>1; if(x<=mid)SUM(ls,l,mid,x,y); if(y>mid)SUM(rs,mid+1,r,x,y); } inline void MAX(int rt,int l,int r,int x,int y) { if(x<=l&&r<=y) { ans=max(ans,maxx[rt]); re ; } if(lazy[rt])pushdown(rt); int mid=(l+r)>>1; if(x<=mid)MAX(ls,l,mid,x,y); if(y>mid) MAX(rs,mid+1,r,x,y); } inline void MIN(int rt,int l,int r,int x,int y) { if(x<=l&&r<=y) { ans=min(ans,minn[rt]); re ; } if(lazy[rt])pushdown(rt); int mid=(l+r)>>1; if(x<=mid)MIN(ls,l,mid,x,y); if(y>mid) MIN(rs,mid+1,r,x,y); } int main() { int x,y,z; rd(n); inc(i,2,n) { rd(x),rd(y),rd(z); add(x+1,y+1,z); } fa[1]=1; dfs1(1); dfs2(1,1); build(1,1,n); rd(m); char opt[10]; inc(i,1,m) { scanf("%s",opt); rd(x),rd(y); ++x,++y; if(opt[0]=='C') { --x;--y; x=x<<1; int a=e[x].to,b=e[x^1].to; if(deep[a]<deep[b])a^=b^=a^=b; change(1,1,n,sub[a],y); } else if(opt[0]=='N') { while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]])x^=y^=x^=y; reverse(1,1,n,sub[top[x]],sub[x]); x=fa[top[x]]; } if(deep[x]>deep[y])x^=y^=x^=y; if(x!=y) reverse(1,1,n,sub[x]+1,sub[y]); } else if(opt[0]=='S') { ans=0; while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]])x^=y^=x^=y; SUM(1,1,n,sub[top[x]],sub[x]); x=fa[top[x]]; } if(deep[x]>deep[y])x^=y^=x^=y; if(x!=y) SUM(1,1,n,sub[x]+1,sub[y]); printf("%d\n",ans); } else if(opt[1]=='A') { ans=-1000005; while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]])x^=y^=x^=y; MAX(1,1,n,sub[top[x]],sub[x]); x=fa[top[x]]; } if(deep[x]>deep[y])x^=y^=x^=y; if(x!=y) MAX(1,1,n,sub[x]+1,sub[y]); printf("%d\n",ans); } else if(opt[1]=='I') { ans=1000045; while(top[x]!=top[y]) { if(deep[top[x]]<deep[top[y]])x^=y^=x^=y; MIN(1,1,n,sub[top[x]],sub[x]); x=fa[top[x]]; } if(deep[x]>deep[y])x^=y^=x^=y; if(x!=y) MIN(1,1,n,sub[x]+1,sub[y]); printf("%d\n",ans); } } re 0; }