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
正解:$link-cut tree$。
这题是$LCT$板子题,省选前复习一发板子。。
注意$access$的时候一定要$pushup$!!!
1 //It is made by wfj_2048~ 2 #include <algorithm> 3 #include <iostream> 4 #include <complex> 5 #include <cstring> 6 #include <cstdlib> 7 #include <cstdio> 8 #include <vector> 9 #include <cmath> 10 #include <queue> 11 #include <stack> 12 #include <map> 13 #include <set> 14 #define inf (1<<30) 15 #define N (100010) 16 #define il inline 17 #define RG register 18 #define ll long long 19 #define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout) 20 21 using namespace std; 22 23 int sum[N],val[N],rev[N],st[N],fa[N],ch[N][2],n,m; 24 char s[12]; 25 26 il int gi(){ 27 RG int x=0,q=1; RG char ch=getchar(); 28 while ((ch<'0' || ch>'9') && ch!='-') ch=getchar(); 29 if (ch=='-') q=-1,ch=getchar(); 30 while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar(); 31 return q*x; 32 } 33 34 il int isroot(RG int x){ 35 return ch[fa[x]][0]!=x && ch[fa[x]][1]!=x; 36 } 37 38 il void pushup(RG int x){ 39 sum[x]=sum[ch[x][0]]+sum[ch[x][1]]+val[x]; return; 40 } 41 42 il void pushdown(RG int x){ 43 rev[x]=0,rev[ch[x][0]]^=1,rev[ch[x][1]]^=1; 44 swap(ch[x][0],ch[x][1]); return; 45 } 46 47 il void rotate(RG int x){ 48 RG int y=fa[x],z=fa[y],k=ch[y][0]==x; 49 if (!isroot(y)) ch[z][ch[z][1]==y]=x; 50 fa[x]=z,ch[y][k^1]=ch[x][k],fa[ch[x][k]]=y; 51 ch[x][k]=y,fa[y]=x,pushup(y),pushup(x); return; 52 } 53 54 il void splay(RG int x){ 55 RG int top=0; st[++top]=x; 56 for (RG int i=x;!isroot(i);i=fa[i]) st[++top]=fa[i]; 57 for (RG int i=top;i;--i) if (rev[st[i]]) pushdown(st[i]); 58 while (!isroot(x)){ 59 RG int y=fa[x],z=fa[y]; 60 if (!isroot(y)){ 61 if ((ch[z][0]==y)^(ch[y][0]==x)) rotate(x); 62 else rotate(y); 63 } 64 rotate(x); 65 } 66 return; 67 } 68 69 il void access(RG int x){ 70 RG int t=0; 71 while (x){ 72 splay(x),ch[x][1]=t; 73 pushup(x),t=x,x=fa[x]; 74 } 75 return; 76 } 77 78 il void makeroot(RG int x){ 79 access(x),splay(x),rev[x]^=1; return; 80 } 81 82 il void link(RG int x,RG int y){ 83 makeroot(x),fa[x]=y; return; 84 } 85 86 il void cut(RG int x,RG int y){ 87 makeroot(x),access(y),splay(y); 88 ch[y][0]=fa[x]=0; return; 89 } 90 91 il int find(RG int x){ 92 access(x),splay(x); 93 while (ch[x][0]) x=ch[x][0]; 94 return x; 95 } 96 97 il int query(RG int x,RG int y){ 98 makeroot(x),access(y),splay(y); 99 return sum[y]; 100 } 101 102 il void work(){ 103 n=gi(); 104 for (RG int i=1;i<=n;++i) 105 val[i]=gi(),sum[i]=val[i]; 106 m=gi(); 107 for (RG int i=1,x,y;i<=m;++i){ 108 scanf("%s",s),x=gi(),y=gi(); 109 if (s[0]=='b'){ 110 if (find(x)==find(y)) puts("no"); 111 else link(x,y),puts("yes"); 112 } 113 if (s[0]=='p') val[x]=y,splay(x); 114 if (s[0]=='e'){ 115 if (find(x)!=find(y)) puts("impossible"); 116 else printf("%d ",query(x,y)); 117 } 118 } 119 return; 120 } 121 122 int main(){ 123 File("travel"); 124 work(); 125 return 0; 126 }