1180: [CROATIAN2009]OTOCI(LCT)
1180: [CROATIAN2009]OTOCI
Time Limit: 50 Sec Memory Limit: 162 MBSubmit: 1200 Solved: 747
[Submit][Status][Discuss]
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
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
code
1 #include<cstdio> 2 #include<algorithm> 3 4 using namespace std; 5 6 const int N = 50010; 7 8 int val[N],fa[N],ch[N][2],rev[N],sum[N],st[N],top; 9 10 void pushup(int x) { 11 sum[x] = sum[ch[x][1]] + sum[ch[x][0]] + val[x]; 12 } 13 void pushdown(int x) { 14 int l = ch[x][0],r = ch[x][1]; 15 if (rev[x]) { 16 rev[l] ^= 1;rev[r] ^= 1; 17 swap(ch[x][0],ch[x][1]); 18 rev[x] ^= 1; 19 } 20 } 21 bool isroot(int x) { 22 return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x; 23 } 24 int son(int x) { 25 return ch[fa[x]][1]==x; 26 } 27 void rotate(int x) { 28 int y = fa[x],z = fa[y],b = son(x),c = son(y),a = ch[x][!b]; 29 if (!isroot(y)) ch[z][c] = x;fa[x] = z; 30 ch[x][!b] = y;fa[y] = x; 31 ch[y][b] = a;if (a) fa[a] = y; 32 pushup(y);pushup(x); 33 } 34 void splay(int x) { 35 top = 0;st[++top] = x; 36 for (int i=x; !isroot(i); i=fa[i]) st[++top] = fa[i]; 37 while (top) pushdown(st[top--]); 38 while (!isroot(x)) { 39 int y = fa[x]; 40 if (!isroot(y)) { 41 if (son(x)==son(y)) rotate(y); 42 else rotate(x); 43 } 44 rotate(x); 45 } 46 } 47 void access(int x) { 48 for (int t=0; x; t=x,x=fa[x]) { 49 splay(x);ch[x][1] = t;pushup(x); 50 } 51 } 52 void makeroot(int x) { 53 access(x); 54 splay(x); 55 rev[x] ^= 1; 56 } 57 void link(int x,int y) { 58 makeroot(x); 59 fa[x] = y; 60 } 61 void update(int x,int y) { 62 makeroot(x);val[x] = y;pushup(x); 63 } 64 int query(int x,int y) { 65 makeroot(x);access(y);splay(y); 66 return sum[y]; 67 } 68 int find(int x) { 69 access(x);splay(x); 70 while (ch[x][0]) x = ch[x][0]; 71 return x; 72 } 73 int main() { 74 int n,m,x,y; 75 char opt[20]; 76 scanf("%d",&n); 77 for (int i=1; i<=n; ++i) scanf("%d",&val[i]),sum[i] = val[i]; 78 scanf("%d",&m); 79 while (m--) { 80 scanf("%s%d%d",opt,&x,&y); 81 if (opt[0]=='b') { 82 if (find(x)==find(y)) puts("no"); 83 else puts("yes"),link(x,y); 84 } 85 else if (opt[0]=='p') update(x,y); 86 else { 87 if (find(x)!=find(y)) puts("impossible"); 88 else printf("%d\n",query(x,y)); 89 } 90 } 91 return 0; 92 }