BJOI2014 大融合

Posted lcyfrog

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了BJOI2014 大融合相关的知识,希望对你有一定的参考价值。

BJOI2014 大融合

LCT维护子树

这题要维护的是子树的大小,动态加边,用LCT维护

(sz_i) 表示虚儿子的大小之和,(sum_i) 表示子树大小

考虑(sz)什么时候会变

  1. access中,只有一个儿子由虚变实,有一个儿子由实变虚,加减一下就好了

  2. link之后连了虚儿子,需要更新,注意这个时候两个点都必须是根,不然要往上pushup

另外pushup也要改一下

#include<iostream> 
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<bitset>
#include<set>
#define ls ch[x][0]
#define rs ch[x][1] 
using namespace std;
inline int read(){
    int x=0,pos=1;char ch=getchar();
    for(;!isdigit(ch);ch=getchar()) if(ch=='-') pos=0;
    for(;isdigit(ch);ch=getchar()) x=(x<<1)+(x<<3)+ch-'0';
    return pos?x:-x;
}
const int N = 100201;
int ch[N][2],fa[N],sum[N],r[N],sz[N];
char s[2];
int nroot(int x){return ch[fa[x]][1]==x||ch[fa[x]][0]==x;}
void push_up(int x){sum[x]=sum[ls]+sum[rs]+sz[x]+1;}
void pushr(int x){swap(ls,rs);r[x]^=1;}
void push_down(int x){if(r[x]){if(ls)pushr(ls); if(rs)pushr(rs); r[x]=0; }}
void push(int x){if(nroot(x)) push(fa[x]);push_down(x);} 
int get(int x){return ch[fa[x]][1]==x;}
void rotate(int x){
    int f=fa[x],g=fa[f],kx=get(x),kf=get(f);
    if(nroot(f)) ch[g][kf]=x;fa[x]=g;
    ch[f][kx]=ch[x][kx^1];fa[ch[x][kx^1]]=f;
    ch[x][kx^1]=f;fa[f]=x;
    push_up(f);push_up(x);
}
void splay(int x){
    push(x);
    while(nroot(x)){
        int f=fa[x];
        if(nroot(f)) rotate(get(x)==get(f)?f:x);
        rotate(x);
    }
}
void access(int x){
    for(int y=0;x;y=x,x=fa[x]){
        splay(x);sz[x]+=sum[rs]-sum[y];rs=y;push_up(x);
    }
}
void makeroot(int x){access(x);splay(x);pushr(x);}
int findroot(int x){
    access(x);splay(x);while(ch[x][0]) x=ch[x][0];splay(x);return x;
}
void link(int x,int y){
    makeroot(x);
    if(findroot(y)!=x){
        makeroot(y);
        fa[x]=y;sz[y]+=sum[x];push_up(y);
    }
}
void split(int x,int y){
    makeroot(x);access(y);splay(y);
}
int main(){
    int n=read(),q=read();
    for(int i=1;i<=n;i++) sum[i]=1;
    for(int i=1;i<=q;i++){
        scanf("%s",s);
        if(s[0]=='A'){
            int x=read(),y=read();link(x,y);
        }else{
            int x=read(),y=read();
            split(x,y);
            printf("%lld
",1ll*sum[x]*(sum[y]-sum[x]));
        }
    }
    return 0;
}

以上是关于BJOI2014 大融合的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ:4530: [Bjoi2014]大融合

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

BJOI2014 大融合

P4219 [BJOI2014]大融合(LCT)

BJOI2014 大融合

洛谷P4219 [BJOI2014]大融合(LCT,Splay)