博客园 首页 私信博主 显示目录 隐藏目录 管理 动画

BZOJ:4530: [Bjoi2014]大融合

4530: [Bjoi2014]大融合

 

拿这题作为lct子树查询的练手。本来以为这会是一个大知识点,结果好像只是一个小技巧?

多维护一个虚边连接着的子树大小即可。

#include<cstdio>
#include<cstring>
#include<algorithm>
#define MN 210010
using namespace std;

int p,ca,f;
inline int read(){
    p=0;ca=getchar();f=1;
    while(ca<'0'||ca>'9') {if (ca=='-') f=-1;ca=getchar();}
    while(ca>='0'&&ca<='9') p=p*10+ca-48,ca=getchar();
    return p*f;
}
struct na{
    int y,ne,c,nu;
}b[MN*2];
int fa[MN],n,t,x,y,c,num,id[MN],key[MN],ch[MN][2],ma[MN],st[MN],Si[MN],si[MN];
bool rt[MN],rev[MN];
inline int max(int a,int b){return a>b?a:b;}
inline void up(int x){si[x]=si[ch[x][0]]+si[ch[x][1]]+Si[x]+1;}
inline void pd(int x){if (rev[x]) swap(ch[x][0],ch[x][1]),rev[ch[x][0]]^=1,rev[ch[x][1]]^=1,rev[x]=0;}
inline void rot(int x){
    int y=fa[x],kind=ch[y][1]==x;
    fa[x]=fa[y];
    fa[y]=x;
    ch[y][kind]=ch[x][!kind];
    fa[ch[y][kind]]=y;
    ch[x][!kind]=y;
    if(rt[y]) rt[y]=0,rt[x]=1;else ch[fa[x]][ch[fa[x]][1]==y]=x;
    up(y);up(x);
}
inline void splay(int x){
    int i=x,to=0;
    while (!rt[i]) st[++to]=i,i=fa[i];pd(i);
    for (;to;to--) pd(st[to]);
    while(!rt[x]){
        if (rt[fa[x]]) rot(x);else
        if ((ch[fa[fa[x]]][1]==fa[x])==(ch[fa[x]][1]==x)) rot(fa[x]),rot(x);else rot(x),rot(x);
    }
}
inline void acc(int u){
    int x=0;
    while(u){
        splay(u);
        Si[u]+=si[ch[u][1]]-si[x];
        rt[ch[u][1]]=1;rt[ch[u][1]=x]=0;
        up(u);
        u=fa[x=u];
    }
}
inline void root(int x){acc(x);splay(x);rev[x]^=1;}
inline void link(int x,int y){
    root(x);acc(y);splay(y);
    fa[x]=y;Si[y]+=si[x];
}
inline int qu(int x,int y){
    root(x);acc(y);
    return (Si[x]+1)*(Si[y]+1);
}
char ss[10];
int main(){
    n=read();t=read();
    for (int i=1;i<=n;i++) rt[i]=si[i]=1;
    while(t--){
        scanf("%s",ss);
        x=read();y=read();
        if (ss[0]=='Q') printf("%d\n",qu(x,y));else link(x,y);
    }
}
View Code

 

posted @ 2017-04-18 08:42  swm_sxt  阅读(535)  评论(0编辑  收藏  举报