zoukankan      html  css  js  c++  java
  • [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
    ", (val[x] + 1) * (val[y] + 1));
                //printf("%d
    ", (siz[y] - siz[x]) * siz[x]); 也可以
            }
        }
        return 0;
    }
    
    
  • 相关阅读:
    Lua中的loadfile、dofile、require详解
    100GB以上超大文件上传和断点续传服务器的实现
    50GB以上超大文件上传和断点续传服务器的实现
    20GB以上超大文件上传和断点续传服务器的实现
    10GB以上超大文件上传和断点续传服务器的实现
    Flash 以上超大文件上传和断点续传服务器的实现
    WebUploader 以上超大文件上传和断点续传服务器的实现
    HTML5 以上超大文件上传和断点续传服务器的实现
    VUE 以上超大文件上传和断点续传服务器的实现
    B/S 以上超大文件上传和断点续传服务器的实现
  • 原文地址:https://www.cnblogs.com/zzy2005/p/10601420.html
Copyright © 2011-2022 走看看