1. 程式人生 > >【刷題】BZOJ 1180 [CROATIAN2009]OTOCI

【刷題】BZOJ 1180 [CROATIAN2009]OTOCI

data har const inpu 找到 沒有 put getch utc

Description

給出n個結點以及每個點初始時對應的權值wi。起始時點與點之間沒有連邊。有3類操作:

1、bridge A B:詢問結點A與結點B是否連通。

如果是則輸出“no”。否則輸出“yes”,並且在結點A和結點B之間連一條無向邊。

2、penguins A X:將結點A對應的權值wA修改為X。

3、excursion A B:如果結點A和結點B不連通,則輸出“impossible”。

否則輸出結點A到結點B的路徑上的點對應的權值的和。

給出q個操作,要求在線處理所有操作。

數據範圍:1<=n<=30000, 1<=q<=300000, 0<=wi<=1000。

Input

第一行包含一個整數n(1<=n<=30000),表示節點的數目。

第二行包含n個整數,第i個整數表示第i個節點初始時對應的權值。

第三行包含一個整數q(1<=n<=300000),表示操作的數目。

以下q行,每行包含一個操作,操作的類別見題目描述。

任意時刻每個節點對應的權值都是1到1000的整數。

Output

輸出所有bridge操作和excursion操作對應的輸出,每個一行。

Sample Input

5
4 2 4 5 6
10
excursion 1 1
excursion 1 2
bridge 1 2
excursion 1 2
bridge 3 4
bridge 3 5
excursion 4 5

bridge 1 3
excursion 2 4
excursion 2 5

Sample Output

4
impossible
yes
6
yes
yes
15
yes
15
16

Solution

又找到一道題,可惜是個水題,那也水一水吧
直接上LCT板子,維護sum就可以了
我還多寫了cut,和link裏判聯通性的東東(其實外面有並查集,這根本不需要)

#include<bits/stdc++.h>
#define ui unsigned int
#define ll long long
#define db double
#define ld long double
#define ull unsigned long long
const int MAXN=30000+10; int n,q,fa[MAXN]; #define lc(x) ch[(x)][0] #define rc(x) ch[(x)][1] struct LCT{ int ch[MAXN][2],fa[MAXN],rev[MAXN],sum[MAXN],stack[MAXN],cnt,val[MAXN]; inline bool nroot(int x) { return lc(fa[x])==x||rc(fa[x])==x; } inline void reverse(int x) { std::swap(lc(x),rc(x)); rev[x]^=1; } inline void pushup(int x) { sum[x]=sum[lc(x)]+sum[rc(x)]+val[x]; } inline void pushdown(int x) { if(rev[x]) { if(lc(x))reverse(lc(x)); if(rc(x))reverse(rc(x)); rev[x]=0; } } inline void rotate(int x) { int f=fa[x],p=fa[f],c=(rc(f)==x); if(nroot(f))ch[p][rc(p)==f]=x; fa[ch[f][c]=ch[x][c^1]]=f; fa[ch[x][c^1]=f]=x; fa[x]=p; pushup(f); pushup(x); } inline void splay(int x) { cnt=0; stack[++cnt]=x; for(register int i=x;nroot(i);i=fa[i])stack[++cnt]=fa[i]; while(cnt)pushdown(stack[cnt--]); for(register int y=fa[x];nroot(x);rotate(x),y=fa[x]) if(nroot(y))rotate((lc(y)==x)==(lc(fa[y])==y)?y:x); pushup(x); } inline void access(int x) { for(register int y=0;x;x=fa[y=x])splay(x),rc(x)=y,pushup(x); } inline int findroot(int x) { access(x);splay(x); while(lc(x))pushdown(x),x=lc(x); splay(x); return x; } inline void makeroot(int x) { access(x);splay(x);reverse(x); } inline void split(int x,int y) { makeroot(x);access(y);splay(y); } inline void link(int x,int y) { makeroot(x); if(findroot(y)!=x)fa[x]=y; } inline void cut(int x,int y) { makeroot(x); if(findroot(y)==x&&fa[y]==x&&!rc(y))fa[y]=lc(x)=0,pushup(x); } }; LCT T; #undef lc #undef rc template<typename T> inline void read(T &x) { T data=0,w=1; char ch=0; while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar(); if(ch=='-')w=-1,ch=getchar(); while(ch>='0'&&ch<='9')data=((T)data<<3)+((T)data<<1)+(ch^'0'),ch=getchar(); x=data*w; } template<typename T> inline void write(T x,char c='\0') { if(x<0)putchar('-'),x=-x; if(x>9)write(x/10); putchar(x%10+'0'); if(c!='\0')putchar(c); } template<typename T> inline void chkmin(T &x,T y){x=(y<x?y:x);} template<typename T> inline void chkmax(T &x,T y){x=(y>x?y:x);} template<typename T> inline T min(T x,T y){return x<y?x:y;} template<typename T> inline T max(T x,T y){return x>y?x:y;} inline int found(int x) { if(fa[x]!=x)fa[x]=found(fa[x]); return fa[x]; } int main() { read(n); for(register int i=1;i<=n;++i)read(T.val[i]),fa[i]=i; read(q); while(q--) { char opt[11];int a,b; scanf("%s",opt);read(a);read(b); if(opt[0]=='b') { int x=found(a),y=found(b); if(x!=y) { fa[x]=y;T.link(a,b); puts("yes"); } else puts("no"); } if(opt[0]=='p')T.access(a),T.splay(a),T.val[a]=b,T.pushup(a); if(opt[0]=='e') { int x=found(a),y=found(b); if(fa[x]!=y)puts("impossible"); else T.split(a,b),write(T.sum[b],'\n'); } } return 0; }

【刷題】BZOJ 1180 [CROATIAN2009]OTOCI