BZOJ2157: 旅游(LCT)
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
解题思路:
查链的套路。
新的技巧,将边变为点连入图。也就是点-边-点,这样就不用特殊处理了^_^
代码:
#include<cstdio> #include<cstring> #include<algorithm> #define lll tr[spc].ch[0] #define rrr tr[spc].ch[1] #define ls ch[0] #define rs ch[1] using std::max; using std::min; using std::swap; struct trnt{ int ch[2]; int fa; int val; int sum; int mx; int mn; int lzt; int mul; bool anc; }tr[1000000]; int wher[1000000]; int n,m; int cnt; char cmd[10]; bool whc(int spc) { return tr[tr[spc].fa].rs==spc; } void pushup(int spc) { if(!spc) return ; tr[spc].mx=max(tr[lll].mx,tr[rrr].mx); tr[spc].mn=min(tr[lll].mn,tr[rrr].mn); if(spc>n) { tr[spc].mx=max(tr[spc].val,tr[spc].mx); tr[spc].mn=min(tr[spc].val,tr[spc].mn); } tr[spc].sum=tr[spc].val+tr[lll].sum+tr[rrr].sum; return ; } void trr(int spc) { if(!spc) return ; swap(lll,rrr); tr[spc].lzt^=1; return ; } void Mul(int spc) { if(!spc) return ; tr[spc].val*=-1; tr[spc].mx*=-1; tr[spc].mn*=-1; tr[spc].sum*=-1; swap(tr[spc].mn,tr[spc].mx); tr[spc].mul^=1; return ; } void pushdown(int spc) { if(tr[spc].lzt) { trr(lll); trr(rrr); tr[spc].lzt=0; } if(tr[spc].mul) { Mul(lll); Mul(rrr); tr[spc].mul=0; } return ; } void recal(int spc) { if(!tr[spc].anc) recal(tr[spc].fa); pushdown(spc); return ; } void rotate(int spc) { int f=tr[spc].fa; bool k=whc(spc); tr[f].ch[k]=tr[spc].ch[!k]; tr[spc].ch[!k]=f; if(tr[f].anc) { tr[spc].anc=1; tr[f].anc=0; }else tr[tr[f].fa].ch[whc(f)]=spc; tr[spc].fa=tr[f].fa; tr[f].fa=spc; tr[tr[f].ch[k]].fa=f; pushup(f); pushup(spc); return ; } void splay(int spc) { recal(spc); while(!tr[spc].anc) { int f=tr[spc].fa; if(tr[f].anc) { rotate(spc); return ; } if(whc(spc)^whc(f)) rotate(spc); else rotate(f); rotate(spc); } return ; } void access(int spc) { int lst=0; while(spc) { splay(spc); tr[rrr].anc=1; tr[lst].anc=0; rrr=lst; pushup(spc); lst=spc; spc=tr[spc].fa; } return ; } void Mtr(int spc) { access(spc); splay(spc); trr(spc); return ; } void split(int x,int y) { Mtr(x); access(y); splay(y); } void link(int x,int y) { Mtr(x); tr[x].fa=y; return ; } int main() { tr[0].mn=0x3f3f3f3f; tr[0].mx=-0x3f3f3f3f; scanf("%d",&n); cnt=n; for(int i=1;i<=2*n;i++) tr[i].anc=1; for(int i=1;i<n;i++) { int a,b,c; scanf("%d%d%d",&a,&b,&c); a++; b++; wher[i]=++cnt; tr[cnt].sum=tr[cnt].val=tr[cnt].mx=tr[cnt].mn=c; link(a,cnt); link(b,cnt); } scanf("%d",&m); while(m--) { scanf("%s",cmd); if(cmd[0]=='C') { int i,w; scanf("%d%d",&i,&w); splay(wher[i]); tr[wher[i]].val=w; pushup(wher[i]); }else if(cmd[0]=='N') { int u,v; scanf("%d%d",&u,&v); u++; v++; split(u,v); Mul(v); }else if(cmd[0]=='S') { int u,v; scanf("%d%d",&u,&v); u++; v++; split(u,v); printf("%d\n",tr[v].sum); }else if(cmd[1]=='A') { int u,v; scanf("%d%d",&u,&v); u++; v++; split(u,v); printf("%d\n",tr[v].mx); }else{ int u,v; scanf("%d%d",&u,&v); u++; v++; split(u,v); printf("%d\n",tr[v].mn); } } return 0; }