[BJOI2014]大融合(LCT)

题面

luogu

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;
}

posted @ 2019-03-26 17:13  zzy2005  阅读(178)  评论(0编辑  收藏  举报