【题意分析】
权当复习LCT吧,操作很简单:
- bridge:直接findroot判一下连通性就好了,如果不连通就link
- penguins:splay一下然后改一下权值
- excursion:判一下连通性之后split把路径拉出来就好了
关于连通性的判法:直接findroot(x)==findroot(y)当然可以,一次makeroot(x)之后x就是根了,然后一次findroot(y)看看是不是x就行了
修改权值后,maintain操作加不加都没关系。
Code:
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cctype>
#include <algorithm>
#define MAXN 100000
using namespace std;
bool rev[MAXN];
int son[MAXN][2], val[MAXN], a[MAXN], father[MAXN], stack[MAXN], n, q;
inline int read () {
register int s = 0, w = 1;
register char ch = getchar ();
while (! isdigit (ch)) {if (ch == '-') w = -1; ch = getchar ();}
while (isdigit (ch)) {s = (s << 3) + (s << 1) + (ch ^ 48); ch = getchar ();}
return s * w;
}
namespace LCT {
inline bool isroot (int x) {return ! (son[father[x]][0] == x || son[father[x]][1] == x);}
inline void maintain (int x) {val[x] = a[x] + val[son[x][0]] + val[son[x][1]];}
inline void pushrev (int x) {swap (son[x][0], son[x][1]), rev[x] ^= 1;}
inline void pushdown (int x) {
if (rev[x]) {
if (son[x][0]) pushrev (son[x][0]);
if (son[x][1]) pushrev (son[x][1]);
rev[x] ^= 1;
}
}
inline void rotate (int x) {
int y = father[x], z = father[y];
int k = son[y][1] == x, kk = son[z][1] == y;
if (! isroot (y)) son[z][kk] = x;
father[x] = z;
son[y][k] = son[x][k ^ 1];
father[son[x][k ^ 1]] = y;
son[x][k ^ 1] = y;
father[y] = x;
maintain (y), maintain (x);
}
inline void splay (int x) {
int top = 0; stack[++top] = x;
for (register int i = x; ! isroot (i); i = father[i]) stack[++top] = father[i];
for (register int i = top; i; i--) pushdown (stack[i]);
while (! isroot (x)) {
int y = father[x], z = father[y];
if (! isroot (y))
(son[y][1] == x) ^ (son[z][1] == y)
? rotate (x) : rotate (y);
rotate (x);
}
maintain (x);
}
inline void access (int x) {for(int y=0;x;x=father[y=x])splay(x),son[x][1]=y,maintain(x);}
inline void makeroot (int x) {access(x),splay(x),pushrev(x);}
inline int findroot (int x) {access(x),splay(x);while(son[x][0])pushdown(x=son[x][0]);splay(x);return 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)father[x]=y;}
}using namespace LCT;
int main () {
n = read ();
for (register int i = 1; i <= n; i++) a[i] = read ();
q = read ();
for (register int I = 1; I <= q; I++) {
char opt[20]; scanf ("%s\n", opt); int x = read (), y = read ();
if (opt[0] == 'b') {
makeroot (x);
if (findroot (y) == x) puts ("no");
else puts ("yes"), link (x, y);
}
if (opt[0] == 'p') {
splay (x), a[x] = y;
}
if (opt[0] == 'e') {
makeroot (x);
if (findroot (y) == x) split (x, y), printf ("%d\n", val[y]);
else puts ("impossible");
}
}
return 0;
}