BZOJ 2157: 旅游
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。
Solution
這題可以直接用樹鏈剖分+線段樹維護。
但我用的是 Link-Cut-Tree 練練手。
注意權值在邊上,可以在兩個點之間加一個有權值的虛點來維護即可。
還要注意上傳標記的時候在點為虛點(有權值)的時候才更新最大最小值。
如果要提取一個區間 [x,y] 的話,先 make_root(x) ,保證在這條實鏈中 x 之前沒有點。
之后再 access(y) , splay(y) ,保證在這棵 Splay 中 y 沒有右兒子。
這時候節點 y 即代表區間 [x,y] !直接在 y<script type="math/tex" id="MathJax-Element-500">y</script> 上操作即可。
Code
#include<cstdio> #include<algorithm> #include<cctype> using namespace std; const int N=4e4+2; int n,tot,top; int fa[N],s[N][2],st[N],num[N]; int key[N],mx[N],mn[N],sum[N],c[N]; bool rev[N],opp[N]; inline int read() {int X=0,w=0; char ch=0;while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();return w?-X:X; } inline int max(int x,int y) {return x>y?x:y; } inline int min(int x,int y) {return x<y?x:y; } inline void write(int x) {if(x<0) putchar('-'),x=-x;if(x>9) write(x/10);putchar(x%10+'0'); } inline void writeln(int x) {write(x),putchar('\n'); } inline bool pd(int x) {return x==s[fa[x]][1]; } inline bool isroot(int x) {return s[fa[x]][0]^x && s[fa[x]][1]^x; } inline void modify(int x) {if(x) swap(s[x][0],s[x][1]),rev[x]^=1; } inline void add(int x,int val) {if(x) key[x]+=val,sum[x]+=val,mx[x]+=val,mn[x]+=val; } inline void change(int x) {if(!x) return;swap(mx[x],mn[x]),mx[x]=-mx[x],mn[x]=-mn[x];key[x]=-key[x],sum[x]=-sum[x],opp[x]^=1; } inline void update(int x) {mx[x]=max(mx[s[x][0]],mx[s[x][1]]);mn[x]=min(mn[s[x][0]],mn[s[x][1]]);if(x>n) mx[x]=max(mx[x],key[x]),mn[x]=min(mn[x],key[x]);sum[x]=sum[s[x][0]]+sum[s[x][1]]+key[x]; } inline void down(int x) {if(rev[x]){modify(s[x][0]),modify(s[x][1]);rev[x]=false;}if(c[x]){add(s[x][0],c[x]),add(s[x][1],c[x]);c[x]=0;}if(opp[x]){change(s[x][0]),change(s[x][1]);opp[x]=false;} } inline void rotate(int x) {int y=fa[x],w=pd(x);if(s[y][w]=s[x][w^1]) fa[s[x][w^1]]=y;if((fa[x]=fa[y]) && !isroot(y)) s[fa[y]][pd(y)]=x;s[fa[y]=x][w^1]=y;update(y); } inline void splay(int x) {for(int y=st[top=1]=x;!isroot(y);y=fa[y]) st[++top]=fa[y];while(top) down(st[top--]);for(int y;!isroot(x);rotate(x))if(!isroot(y=fa[x])) rotate(pd(x)==pd(y)?y:x);update(x); } inline void access(int x) {for(int y=0;x;x=fa[y=x]) splay(x),s[x][1]=y,update(x); } inline void mkroot(int x) {access(x),splay(x),modify(x); } inline void link(int x,int y) {mkroot(x),fa[x]=y; } inline int getsum(int x,int y) {mkroot(x),access(y),splay(y);return sum[y]; } inline int getmax(int x,int y) {mkroot(x),access(y),splay(y);return mx[y]; } inline int getmin(int x,int y) {mkroot(x),access(y),splay(y);return mn[y]; } inline void reverse(int x,int y) {mkroot(x),access(y),splay(y);change(y); } int main() {n=tot=read();mx[0]=-1e9,mn[0]=1e9;for(int i=1;i<n;i++){int x=read()+1,y=read()+1,z=read();num[i]=++tot,link(x,tot),link(y,tot);key[tot]=mx[tot]=mn[tot]=sum[tot]=z;}int m=read();while(m--){char ch=getchar();while(ch^'C' && ch^'X' && ch^'I' && ch^'S' && ch^'N') ch=getchar();if(ch=='S') writeln(getsum(read()+1,read()+1)); elseif(ch=='X') writeln(getmax(read()+1,read()+1)); elseif(ch=='I') writeln(getmin(read()+1,read()+1)); elseif(ch=='N') reverse(read()+1,read()+1); else{int x=num[read()],val=read();access(x),key[x]=val,update(x);}}return 0; }總結
以上是生活随笔為你收集整理的BZOJ 2157: 旅游的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: BZOJ 2049: [Sdoi2008
- 下一篇: BZOJ 2002: [Hnoi2010