Loj 2230. 「BJOI2014」大融合 (LCT 维护子树信息)

链接:https://loj.ac/problem/2230

 

思路:

设立siz数组保存虚点信息,sum表示总信息

维护子树信息link操作和access操作需要进行一些改动

可参考博客:https://www.cnblogs.com/GXZlegend/p/7061458.html

实现代码;

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ls c[x][0]
#define rs c[x][1]
const int M = 4e5+10;
const int inf = 1e9;
int top;
int sum[M],c[M][2],val[M],fa[M],rev[M],mn[M],S[M];
int siz[M];
inline void up(int x){
    sum[x] = sum[ls] + sum[rs] + siz[x] + 1;
}

inline void pushrev(int x){
    swap(ls,rs); rev[x] ^= 1;
}

inline bool isroot(int x){
    return c[fa[x]][0]!=x&&c[fa[x]][1]!=x;
}

inline void rotate(int x){
    int y = fa[x],z = fa[y];
    int k = c[y][1] == x;
    if(!isroot(y)) c[z][c[z][1]==y]=x;
    fa[x] = z;
    c[y][k] = c[x][k^1]; fa[c[x][k^1]] = y;
    c[x][k^1] = y; fa[y] = x;
    up(y); up(x);
}

inline void pushdown(int x){
    if(rev[x]){
        if(ls) pushrev(ls);
        if(rs) pushrev(rs);
        rev[x] = 0;
    }
}

inline void splay(int x){
    S[top=1]=x;
    for(int i = x;!isroot(i);i=fa[i]) S[++top] = fa[i];
    while(top) pushdown(S[top--]);
    while(!isroot(x)){
        int y = fa[x],z = fa[y];
        if(!isroot(y))
            (c[y][1]==x)^(c[z][1]==y)?rotate(x):rotate(y);
        rotate(x);
    }
}

inline void access(int x){
    //维护子树
    for(int y = 0;x;y = x,x = fa[x])
        splay(x),siz[x] += sum[rs] - sum[y],c[x][1] = y,up(x);
    //for(int y = 0;x;y = x,x = fa[x])
        //splay(x),c[x][1] = y,up(x);
}

inline void makeroot(int x){
    access(x); splay(x); pushrev(x);
}

inline void split(int x,int y){
    makeroot(x); access(y); splay(y);
}

inline void link(int x,int y){
    //维护子树
    makeroot(x); makeroot(y); fa[x] = y; siz[y]+=sum[x]; up(y);
   // makeroot(x);fa[x] = y;
}

inline void cut(int x,int y){
    split(x,y); fa[x] = c[y][0] = 0; up(y);
}

inline int findroot(int x){
    access(x); splay(x);
    while(ls) x = ls;
    return x;
}

int main()
{
    int n,q,u,v;
    scanf("%d%d",&n,&q);
    char op[10];
    while(q--){
        scanf("%s",op); scanf("%d%d",&u,&v);
        if(op[0] == 'A') link(u,v);
        else {
            split(u,v);
            printf("%lld\n",1LL*sum[u]*(sum[v]-sum[u]));
        }
    }
}

 

posted @ 2019-04-30 20:42  冥想选手  阅读(166)  评论(0编辑  收藏  举报