BZOJ2157: 旅游
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
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
2
1
-1
5
3
HINT
一共有10 个数据,对于第i (1 <= i <= 10) 个数据, N = M = i * 2000。
题解Here!
#include<iostream> #include<algorithm> #include<cstdio> #define LSON rt<<1 #define RSON rt<<1|1 #define DATA1(x) b[x].data1 #define DATA2(x) b[x].data2 #define DATA3(x) b[x].data3 #define SIGN(x) b[x].c #define LSIDE(x) b[x].l #define RSIDE(x) b[x].r #define WIDTH(x) (RSIDE(x)-LSIDE(x)+1) #define MAXN 100010 #define MAX 2147483647 using namespace std; int n,m,c=1,d=1; int head[MAXN],deep[MAXN],son[MAXN],size[MAXN],fa[MAXN],id[MAXN],top[MAXN]; struct node1{ int next,to,w; }a[MAXN<<1]; struct node2{ int data1,data2,data3,c; int l,r; }b[MAXN<<2]; struct node3{ int u,v,w; }g[MAXN]; inline int read(){ int date=0,w=1;char c=0; while(c<'0'||c>'9'){if(c=='-')w=-1;c=getchar();} while(c>='0'&&c<='9'){date=date*10+c-'0';c=getchar();} return date*w; } inline int max(const int x,const int y){return x>y?x:y;} inline int min(const int x,const int y){return x<y?x:y;} inline void add(int u,int v,int w){ a[c].to=v;a[c].w=w; a[c].next=head[u]; head[u]=c++; a[c].to=u;a[c].w=w; a[c].next=head[v]; head[v]=c++; } void dfs1(int rt){ son[rt]=0;size[rt]=1; for(int i=head[rt];i;i=a[i].next){ int will=a[i].to; if(!deep[will]){ deep[will]=deep[rt]+1; fa[will]=rt; dfs1(will); size[rt]+=size[will]; if(size[will]>size[son[rt]])son[rt]=will; } } } void dfs2(int rt,int f){ id[rt]=d++;top[rt]=f; if(son[rt])dfs2(son[rt],f); for(int i=head[rt];i;i=a[i].next){ int will=a[i].to; if(will!=fa[rt]&&will!=son[rt]) dfs2(will,will); } } inline void pushup(int rt){ DATA1(rt)=DATA1(LSON)+DATA1(RSON); DATA2(rt)=max(DATA2(LSON),DATA2(RSON)); DATA3(rt)=min(DATA3(LSON),DATA3(RSON)); } inline void pushdown(int rt){ if(!SIGN(rt)||LSIDE(rt)==RSIDE(rt))return; SIGN(LSON)^=SIGN(rt); DATA1(LSON)=-DATA1(LSON);DATA2(LSON)=-DATA2(LSON);DATA3(LSON)=-DATA3(LSON); swap(DATA2(LSON),DATA3(LSON)); SIGN(RSON)^=SIGN(rt); DATA1(RSON)=-DATA1(RSON);DATA2(RSON)=-DATA2(RSON);DATA3(RSON)=-DATA3(RSON); swap(DATA2(RSON),DATA3(RSON)); SIGN(rt)=0; } void buildtree(int l,int r,int rt){ int mid; LSIDE(rt)=l; RSIDE(rt)=r; if(l==r){ DATA1(rt)=DATA2(rt)=DATA3(rt)=0; return; } mid=l+r>>1; buildtree(l,mid,LSON); buildtree(mid+1,r,RSON); pushup(rt); } void update_change(int l,int r,int c,int rt){ int mid; if(l<=LSIDE(rt)&&RSIDE(rt)<=r){ DATA1(rt)=DATA2(rt)=DATA3(rt)=c; return; } pushdown(rt); mid=LSIDE(rt)+RSIDE(rt)>>1; if(l<=mid)update_change(l,r,c,LSON); if(mid<r)update_change(l,r,c,RSON); pushup(rt); } void update_null(int l,int r,int rt){ int mid; if(l<=LSIDE(rt)&&RSIDE(rt)<=r){ SIGN(rt)^=1; DATA1(rt)=-DATA1(rt);DATA2(rt)=-DATA2(rt);DATA3(rt)=-DATA3(rt); swap(DATA2(rt),DATA3(rt)); return; } pushdown(rt); mid=LSIDE(rt)+RSIDE(rt)>>1; if(l<=mid)update_null(l,r,LSON); if(mid<r)update_null(l,r,RSON); pushup(rt); } int query_sum(int l,int r,int rt){ int mid,ans=0; if(l<=LSIDE(rt)&&RSIDE(rt)<=r) return DATA1(rt); pushdown(rt); mid=LSIDE(rt)+RSIDE(rt)>>1; if(l<=mid)ans+=query_sum(l,r,LSON); if(mid<r)ans+=query_sum(l,r,RSON); return ans; } int query_max(int l,int r,int rt){ int mid,ans=-MAX; if(l<=LSIDE(rt)&&RSIDE(rt)<=r) return DATA2(rt); pushdown(rt); mid=LSIDE(rt)+RSIDE(rt)>>1; if(l<=mid)ans=max(ans,query_max(l,r,LSON)); if(mid<r)ans=max(ans,query_max(l,r,RSON)); return ans; } int query_min(int l,int r,int rt){ int mid,ans=MAX; if(l<=LSIDE(rt)&&RSIDE(rt)<=r) return DATA3(rt); pushdown(rt); mid=LSIDE(rt)+RSIDE(rt)>>1; if(l<=mid)ans=min(ans,query_min(l,r,LSON)); if(mid<r)ans=min(ans,query_min(l,r,RSON)); return ans; } void work1(int x,int y){ while(top[x]!=top[y]){ if(deep[top[x]]<deep[top[y]])swap(x,y); update_null(id[top[x]],id[x],1); x=fa[top[x]]; } if(deep[x]>deep[y])swap(x,y); update_null(id[x]+1,id[y],1); return; } void work2(int x,int y){ int s=0; while(top[x]!=top[y]){ if(deep[top[x]]<deep[top[y]])swap(x,y); s+=query_sum(id[top[x]],id[x],1); x=fa[top[x]]; } if(deep[x]>deep[y])swap(x,y); s+=query_sum(id[x]+1,id[y],1); printf("%d\n",s); return; } void work3(int x,int y){ int s=-MAX; while(top[x]!=top[y]){ if(deep[top[x]]<deep[top[y]])swap(x,y); s=max(s,query_max(id[top[x]],id[x],1)); x=fa[top[x]]; } if(deep[x]>deep[y])swap(x,y); s=max(s,query_max(id[x]+1,id[y],1)); printf("%d\n",s); return; } void work4(int x,int y){ int s=MAX; while(top[x]!=top[y]){ if(deep[top[x]]<deep[top[y]])swap(x,y); s=min(s,query_min(id[top[x]],id[x],1)); x=fa[top[x]]; } if(deep[x]>deep[y])swap(x,y); s=min(s,query_min(id[x]+1,id[y],1)); printf("%d\n",s); return; } void work(){ char ch[10]; int x,y; m=read(); while(m--){ scanf("%s",ch);x=read()+1;y=read()+1; switch(ch[0]){ case 'C':{ x--;y--; update_change(id[g[x].v],id[g[x].v],y,1); break; } case 'N':work1(x,y);break; case 'S':work2(x,y);break; case 'M':{ if(ch[1]=='A')work3(x,y); if(ch[1]=='I')work4(x,y); break; } } } } void init(){ n=read(); for(int i=1;i<n;i++){ g[i].u=read()+1;g[i].v=read()+1;g[i].w=read(); add(g[i].u,g[i].v,g[i].w); } deep[1]=1; dfs1(1); dfs2(1,1); buildtree(1,n,1); for(int i=1;i<n;i++){ if(deep[g[i].u]>deep[g[i].v])swap(g[i].u,g[i].v); update_change(id[g[i].v],id[g[i].v],g[i].w,1); } } int main(){ init(); work(); return 0; }