[BZOJ 4530] [BJOI 2014] 大融合

Description

题面

Solution

\(LCT\) 维护子树信息,\(son[x]\) 表示 \(x\) 的虚儿子的子树大小,\(siz[x]\) 表示 \(x\) 的实儿子的子树大小。

Code

#include <cstdio>

const int N = 100005;
char opt; int siz[N], son[N], ch[N][2], fa[N], tag[N];

int read() {
    int x = 0; char c = getchar();
    while (c < '0' || c > '9') c = getchar();
    while (c >= '0' && c <= '9') {
        x = (x << 3) + (x << 1) + (c ^ 48);
        c = getchar();
    }
    return x;
}
void swap(int &x, int &y) {
    x ^= y, y ^= x, x ^= y;
}
int get(int x) {
    return ch[fa[x]][1] == x;
}
int isroot(int x) {
    return ch[fa[x]][0] != x && ch[fa[x]][1] != x;
}
void maintain(int x) {
    siz[x] = son[x] + siz[ch[x][0]] + siz[ch[x][1]] + 1;
}
void pushdown(int x) {
    if (ch[x][0]) tag[ch[x][0]] ^= 1;
    if (ch[x][1]) tag[ch[x][1]] ^= 1;
    swap(ch[x][0], ch[x][1]), tag[x] = 0;
}
void push(int x) {
    if (!isroot(x)) push(fa[x]);
    if (tag[x]) pushdown(x);
}
void rotate(int x) {
    int y = fa[x], z = fa[y], k = get(x);
    if (!isroot(y)) ch[z][ch[z][1]==y] = x;
    ch[y][k] = ch[x][k^1], ch[x][k^1] = y;
    fa[ch[y][k]] = y, fa[y] = x, fa[x] = z;
    maintain(y), maintain(x);
}
void splay(int x) {
    push(x);
    for (int y; !isroot(x); rotate(x))
        if (!isroot(y=fa[x])) rotate(get(x) ^ get(y) ? x : y);
}
void access(int x) { //
    for (int y = 0; x; y = x, x = fa[x]) {
        splay(x);
        son[x] += siz[ch[x][1]] - siz[y];
        ch[x][1] = y, maintain(x);
    }
}
void makeroot(int x) {
    access(x), splay(x), tag[x] ^= 1;
}
void link(int x, int y) { //要access(y), splay(y), 否则y以上的部分不会更新
    makeroot(x), access(y), splay(y);
    son[y] += siz[x], fa[x] = y, maintain(y);
}
long long query(int x, int y) { //由于access(y)可能会更改根, 因此要splay(x)
    makeroot(x), access(y), splay(x);
    return 1LL * (son[x] + 1) * (son[y] + 1);
}

int main() {
    int n = read(), m = read();
    for (int i = 1; i <= n; ++i) siz[i] = 1;
    while (m--) {
        scanf("%c", &opt);
        int x = read(), y = read();
        if (opt == 'A') link(x, y);
        else printf("%lld\n", query(x, y));
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/fly-in-milkyway/p/10036131.html