极地旅行社
Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 1010 Solved: 597
[Submit][Status][Discuss]
Description
不久之前,Mirko建立了一个旅行社,名叫“极地之梦”。这家旅行社在北极附近购买了N座冰岛,并且提供观光服
务。当地最受欢迎的当然是帝企鹅了,这些小家伙经常成群结队的游走在各个冰岛之间。Mirko的旅行社遭受一次
重大打击,以至于观光游轮已经不划算了。旅行社将在冰岛之间建造大桥,并用观光巴士来运载游客。Mirko希望
开发一个电脑程序来管理这些大桥的建造过程,以免有不可预料的错误发生。这些冰岛从1到N标号。一开始时这些
岛屿没有大桥连接,并且所有岛上的帝企鹅数量都是知道的。每座岛上的企鹅数量虽然会有所改变,但是始终在[0
, 1000]之间。你的程序需要处理以下三种命令:
1."bridge A B"——在A与B之间建立一座大桥(A与B是不同的岛屿)。由于经费限制,这项命令被接受,当且仅当
A与B不联通。若这项命令被接受,你的程序需要输出"yes",之
后会建造这座大桥。否则,你的程序需要输出"no"。
2."penguins A X"——根据可靠消息,岛屿A此时的帝企鹅数量变为X。这项命令只是用来提供信息的,你的程序不
需要回应。
3."excursion A B"——一个旅行团希望从A出发到B。若A与B连通,你的程序需要输出这个旅行团一路上所能看到的
帝企鹅数量(包括起点A与终点B),若不联通,你的程序需要输出"impossible"。
Input
第一行一个正整数N,表示冰岛的数量。
第二行N个范围[0, 1000]的整数,为每座岛屿初始的帝企鹅数量。
第三行一个正整数M,表示命令的数量。接下来M行即命令,为题目描述所示。
1<=N<=30000,1<=M<=100000
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
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
impossible
yes
6
yes
yes
15
yes
15
16
HINT
Source
题解:模板题
1 #include<cstring> 2 #include<cmath> 3 #include<algorithm> 4 #include<iostream> 5 #include<cstdio> 6 7 #define N 30007 8 using namespace std; 9 inline int read() 10 { 11 int x=0,f=1;char ch=getchar(); 12 while(ch>'9'||ch<'0'){if (ch=='-') f=-1;ch=getchar();} 13 while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();} 14 return x*f; 15 } 16 17 int n,m; 18 int sum[N],num[N],rev[N]; 19 int c[N][2],fa[N],st[N]; 20 21 void update(int p) 22 { 23 int l=c[p][0],r=c[p][1]; 24 sum[p]=sum[l]+sum[r]+num[p]; 25 } 26 void pushdown(int p) 27 { 28 int l=c[p][0],r=c[p][1]; 29 if (rev[p]) 30 { 31 rev[p]^=1,rev[l]^=1,rev[r]^=1; 32 swap(c[p][0],c[p][1]); 33 } 34 } 35 inline bool isroot(int x) 36 { 37 return c[fa[x]][0]!=x&&c[fa[x]][1]!=x; 38 } 39 void rotate(int x) 40 { 41 int y=fa[x],z=fa[y],l,r; 42 if (c[y][0]==x) l=0;else l=1;r=l^1; 43 if (!isroot(y)) 44 { 45 if (c[z][0]==y) c[z][0]=x; 46 else c[z][1]=x; 47 } 48 fa[x]=z,fa[y]=x,fa[c[x][r]]=y; 49 c[y][l]=c[x][r],c[x][r]=y; 50 update(y),update(x); 51 } 52 void splay(int x) 53 { 54 int top=0;st[++top]=x; 55 for (int i=x;!isroot(i);i=fa[i]) 56 st[++top]=fa[i]; 57 for (int i=top;i>=1;i--) 58 pushdown(st[i]); 59 while(!isroot(x)) 60 { 61 int y=fa[x],z=fa[y]; 62 if (!isroot(y)) 63 { 64 if (c[y][0]==x^c[z][0]==y) rotate(x); 65 else rotate(y); 66 } 67 rotate(x); 68 } 69 } 70 void access(int x) 71 { 72 int t=0; 73 while(x) 74 { 75 splay(x); 76 c[x][1]=t; 77 update(x); 78 t=x,x=fa[x]; 79 } 80 } 81 void makeroot(int x) 82 { 83 access(x); 84 splay(x); 85 rev[x]^=1; 86 } 87 void link(int x,int y) 88 { 89 makeroot(x); 90 fa[x]=y; 91 splay(x); 92 } 93 int find(int x) 94 { 95 access(x),splay(x); 96 int y=x; 97 while(c[y][0]) y=c[y][0]; 98 return y; 99 } 100 void cut(int x,int y) 101 { 102 makeroot(x); 103 access(y); 104 splay(y); 105 fa[x]=c[y][0]=0; 106 } 107 int main() 108 { 109 freopen("fzy.in","r",stdin); 110 freopen("fzy.out","w",stdout); 111 112 n=read(); 113 for (int i=1;i<=n;i++) 114 num[i]=sum[i]=read(); 115 m=read(); 116 while(m--) 117 { 118 char ch[20];scanf("%s",ch); 119 if (ch[0]=='b') 120 { 121 int u=read(),v=read(); 122 if (find(u)!=find(v)) printf("yes "),link(u,v); 123 else printf("no "); 124 } 125 else if (ch[0]=='p') 126 { 127 int x=read(),y=read(); 128 num[x]=y; 129 splay(x); 130 } 131 else 132 { 133 int u=read(),v=read(); 134 if (find(u)!=find(v)) 135 { 136 printf("impossible "); 137 continue; 138 } 139 makeroot(u),access(v),splay(v); 140 printf("%d ",sum[v]); 141 } 142 } 143 }