BZOJ4530 [BJOI2014] 大融合

LCT维护子树信息(

考虑维护两个值,一个虚子树信息,一个全部信息。

因为虚子树只有在link和access的时候改变,可以方便的维护。

具体可以康康代码。

近期考虑写点大代码题练练手。

//Love and Freedom.
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#define ll long long
#define inf 20021225
#define fa(x) t[x].fa
#define ls(x) t[x].son[0]
#define rs(x) t[x].son[1]
#define nrt(x) (ls(fa(x))==x||rs(fa(x))==x)
#define N 100010
using namespace std;
int read()
{
    int s=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9'){if(ch=='-') f=-1; ch=getchar();}
    while(ch>='0'&&ch<='9') s=s*10+ch-'0',ch=getchar();
    return f*s;
}
struct node{int cnt,sum,fa,son[2]; bool tag;}t[N];
void pushup(int x){t[x].sum=1+t[x].cnt+t[ls(x)].sum+t[rs(x)].sum;}
void rotate(int x)
{
    if(!nrt(x) || !x)    return;
    int f=fa(x),gf=fa(f);
    int k=rs(f)==x,p=k^1;
    if(nrt(f))    t[gf].son[rs(gf)==f]=x;
    if(t[x].son[p])    t[t[x].son[p]].fa=f;
    t[f].son[k]=t[x].son[p]; t[x].son[p]=f;
    t[x].fa=gf; t[f].fa=x;
    pushup(f); pushup(x);
}
void pushdown(int x)
{
    if(t[x].tag)
    {
        swap(ls(x),rs(x));
        if(ls(x))    t[ls(x)].tag^=1;
        if(rs(x))    t[rs(x)].tag^=1;
        t[x].tag=0;
    }
}
void push(int x)
{
    if(nrt(x))    push(fa(x));
    pushdown(x);
}
void splay(int x)
{
    push(x);
    while(nrt(x))
    {
        int f=fa(x),gf=fa(f);
        if(nrt(gf))    (rs(f)==x)^(rs(gf)==f)?rotate(x):rotate(f);
        rotate(x);
    }
}
void access(int x)
{
    int y=0;
    do
    {
        splay(x); t[x].cnt+=t[rs(x)].sum-t[y].sum;
        rs(x)=y; pushup(x); y=x; x=fa(x);
    }while(x);
}
void makeroot(int x)
{
    access(x); splay(x); t[x].tag=1;
}
int getroot(int x)
{
    access(x); splay(x);
    while(ls(x))    x=ls(x);
    return x;
}
void split(int x,int y)
{
    makeroot(x); access(y); splay(y);
}
void link(int x,int y)
{
    split(x,y);
    if(getroot(y)==x)    return;
    t[x].fa=y; t[y].cnt+=t[x].sum;
}
ll calc(int x,int y)
{
    split(x,y);
    return 1ll*t[x].sum*(t[y].sum-t[x].sum);
}
char ch[10];
int main()
{
    int n=read(),m=read();
    for(int i=1;i<=n;i++)    t[i].sum=1;
    while(m--)
    {
        scanf("%s",ch); int x=read(),y=read();
        if(ch[0]=='A')    link(x,y);
        else    printf("%lld\n",calc(x,y));
    }
    return 0;
}
View Code

 

posted @ 2019-09-26 11:13  寒雨微凝  阅读(144)  评论(0编辑  收藏  举报