【BZOJ 1180】 (LCT)
1180: [CROATIAN2009]OTOCI
Time Limit: 50 Sec Memory Limit: 162 MB
Submit: 1078 Solved: 662Description
给出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 5Sample Output
4
impossible
yes
6
yes
yes
15
yes
15
16HINT
Source
【分析】
LCT裸题。。
没有cut操作。。
嗯。。。还是要调试啊。。。
注意LCT是维护链的,,询问路径对LCT来说就是小菜一碟。。
不过之前维护子树的那题用LCT变成路径维护的感觉很强啊。。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 using namespace std; 7 #define Maxn 30010 8 9 struct node 10 { 11 int son[2],fa,w,sm; 12 bool rev; 13 node() {son[0]=son[1]=fa=w=sm=rev=0;} 14 }tr[Maxn]; 15 16 int q[Maxn],ql; 17 struct LCT 18 { 19 void upd(int x) 20 { 21 int lc=tr[x].son[0],rc=tr[x].son[1]; 22 tr[x].sm=tr[lc].sm+tr[rc].sm+tr[x].w; 23 } 24 void push_down(int x) 25 { 26 int lc=tr[x].son[0],rc=tr[x].son[1]; 27 if(tr[x].rev) 28 { 29 swap(tr[x].son[0],tr[x].son[1]); 30 tr[lc].rev^=1;tr[rc].rev^=1; 31 tr[x].rev=0; 32 } 33 } 34 bool is_root(int x) 35 { 36 return tr[tr[x].fa].son[0]!=x&&tr[tr[x].fa].son[1]!=x; 37 } 38 void rot(int x) 39 { 40 int fa=tr[x].fa,yy=tr[fa].fa; 41 int w=tr[fa].son[0]==x?1:0; 42 43 if(!is_root(fa)) 44 { 45 if(tr[yy].son[0]==fa) tr[yy].son[0]=x; 46 else tr[yy].son[1]=x; 47 }tr[x].fa=yy; 48 49 tr[tr[x].son[w]].fa=fa; 50 tr[fa].son[1-w]=tr[x].son[w]; 51 52 tr[x].son[w]=fa; 53 tr[fa].fa=x; 54 upd(fa);//upd(x); 55 } 56 void pre(int x) 57 { 58 ql=0; 59 while(!is_root(x)) q[++ql]=x,x=tr[x].fa; 60 q[++ql]=x; 61 while(ql) push_down(q[ql--]); 62 } 63 void splay(int x) 64 { 65 pre(x); 66 while(!is_root(x)) 67 { 68 int fa=tr[x].fa,yy=tr[fa].fa; 69 if(!is_root(fa)) 70 { 71 if((tr[yy].son[0]==fa)==(tr[fa].son[0]==x)) rot(fa); 72 else rot(x); 73 } 74 rot(x); 75 }upd(x); 76 } 77 void access(int x) 78 { 79 int lt=0; 80 while(x) 81 { 82 splay(x); 83 tr[x].son[1]=lt; 84 upd(x); 85 lt=x; 86 x=tr[x].fa; 87 } 88 } 89 void make_root(int x) 90 { 91 access(x); 92 splay(x); 93 tr[x].rev^=1; 94 } 95 void split(int x,int y) 96 { 97 make_root(x); 98 access(y); 99 splay(y); 100 } 101 int find_root(int x) 102 { 103 access(x); 104 splay(x); 105 while(tr[x].son[0]) x=tr[x].son[0]; 106 return x; 107 } 108 bool cn(int x,int y) 109 { 110 return find_root(x)==find_root(y); 111 } 112 void link(int x,int y) 113 { 114 make_root(x); 115 tr[x].fa=y; 116 } 117 }LCT; 118 119 char s[20]; 120 121 int main() 122 { 123 int n; 124 scanf("%d",&n); 125 for(int i=1;i<=n;i++) 126 { 127 int x; 128 scanf("%d",&x); 129 tr[i].w=x;LCT.upd(x); 130 } 131 int q; 132 scanf("%d",&q); 133 while(q--) 134 { 135 int x,y; 136 scanf("%s%d%d",s,&x,&y); 137 if(s[0]=='e') 138 { 139 if(!LCT.cn(x,y)) printf("impossible\n"); 140 else 141 { 142 LCT.split(x,y); 143 printf("%d\n",tr[y].sm); 144 } 145 } 146 else if(s[0]=='b') 147 { 148 if(!LCT.cn(x,y)) {printf("yes\n");LCT.link(x,y);} 149 else printf("no\n"); 150 } 151 else 152 { 153 LCT.splay(x); 154 tr[x].w=y;LCT.upd(x); 155 } 156 } 157 return 0; 158 }
2017-04-27 10:50:31