[BJOI2014]大融合(LCT)
题面
bzoj是权限题..
题解
\(LCT\)维护子树信息
因为\(LCT\)中有一些虚子树,\(splay\)维护不了.
所以要新开一个数组来记录
然后注意\(link\)时
是先\(split(x,y)\)
因为一般的\(link\)是先\(makeroot(x)\)
再\(fa[x] = y\)
然而,如果\(y\)之上还有节点,就无法实时更新
想想,\(split(x,y)\)是怎么操作的
makeroot(x); access(y); splay(y);
这样\(y\)之上就没有节点了
所以只要更新\(y\)这个点即可
Code
#include<bits/stdc++.h>
#define LL long long
#define RG register
using namespace std;
template<class T> inline void read(T &x) {
x = 0; RG char c = getchar(); bool f = 0;
while (c != '-' && (c < '0' || c > '9')) c = getchar(); if (c == '-') c = getchar(), f = 1;
while (c >= '0' && c <= '9') x = x*10+c-48, c = getchar();
x = f ? -x : x;
return ;
}
template<class T> inline void write(T x) {
if (!x) {putchar(48);return ;}
if (x < 0) x = -x, putchar('-');
int len = -1, z[20]; while (x > 0) z[++len] = x%10, x /= 10;
for (RG int i = len; i >= 0; i--) putchar(z[i]+48);return ;
}
const int N = 100010;
int ch[N][2], fa[N], siz[N], val[N];
bool rev[N];
bool isroot(int x) {
return (ch[fa[x]][0] != x && ch[fa[x]][1] != x);
}
#define get(x) (ch[fa[x]][1] == x)
void pushup(int x) { siz[x] = siz[ch[x][0]] + siz[ch[x][1]] + 1 + val[x]; }
void rotate(int x) {
int y = fa[x], z = fa[y], k = get(x);
if (!isroot(y)) ch[z][get(y)] = x;
fa[x] = z;
ch[y][k] = ch[x][k ^ 1]; fa[ch[x][k ^ 1]] = y;
ch[x][k ^ 1] = y; fa[y] = x;
pushup(y);
return ;
}
void putrev(int x) {
swap(ch[x][0], ch[x][1]);
rev[x] ^= 1;
}
void pushdown(int x) {
if (rev[x]) {
if (ch[x][0]) putrev(ch[x][0]);
if (ch[x][1]) putrev(ch[x][1]);
rev[x] = 0;
}
}
int S[N], top;
void splay(int x) {
S[top = 1] = x;
for (int i = x; !isroot(i); i = fa[i]) S[++top] = fa[i];
for (int i = top; i; i--) pushdown(S[i]);
while (!isroot(x)) {
int y = fa[x];
if (!isroot(y))
(get(x) ^ get(y)) ? rotate(x) : rotate(y);
rotate(x);
}
pushup(x);
}
void access(int x) {
for (int y = 0; x; y = x, x = fa[x])
splay(x), val[x] += siz[ch[x][1]] - siz[y], ch[x][1] = y, pushup(x);
}
void makeroot(int x) { access(x); splay(x); putrev(x); }
void split(int x, int y) { makeroot(x); access(y); splay(y); }
void link(int x, int y) {
split(x, y);
fa[x] = y;
val[y] += siz[x];
pushup(y);
}
int main() {
int n, Q;
read(n), read(Q);
while (Q--) {
char c; int x, y;
scanf("%c", &c); read(x), read(y);
if (c == 'A') link(x, y);
else {
split(x, y);
printf("%d\n", (val[x] + 1) * (val[y] + 1));
//printf("%d\n", (siz[y] - siz[x]) * siz[x]); 也可以
}
}
return 0;
}