bzoj3510 首都

题目描述:给你n个点和m个操作:

1.链接两个点。

2.查询某点所在树的重心。

3.查询所有树重心的异或和。

其实就是lct维护虚子树,链接时新重心一定在原来的两重心连线上,相当于splay查询区间第k大值(区间中点)。

代码:

#include<cstdio>
#include<algorithm>
#define N 100050
int n,m;
int fa[N],rt[N],ch[N][2],s[N],sx[N],sr;
bool res[N];
bool is_not_root(int x)
{
    return (ch[fa[x]][0]==x)|(ch[fa[x]][1]==x);
}
void update(int x)
{
    s[x]=s[ch[x][0]]+s[ch[x][1]]+sx[x]+1;
}
void reser(int x)
{
    res[x]^=1;
    std::swap(ch[x][0],ch[x][1]);
}
void pushdown(int x)
{
    if(res[x])
    {
        res[x]=0;
        reser(ch[x][0]);
        reser(ch[x][1]);
    }
}
void down(int x)
{
    if(is_not_root(x))down(fa[x]);
    pushdown(x);
}
void rotate(int x)
{
    int y = fa[x],k = (ch[y][1]==x);
    if(is_not_root(y))ch[fa[y]][ch[fa[y]][1]==y]=x;
    fa[x]=fa[y];
    ch[y][k]=ch[x][!k],fa[ch[x][!k]]=y;
    ch[x][!k]=y,fa[y]=x;
    update(y),update(x);
}
void splay(int x)
{
    down(x);
    while(is_not_root(x))
    {
        int y = fa[x],z=fa[y];
        if(is_not_root(y))
            ((ch[y][1]==x)^(ch[z][1]==y))?rotate(x):rotate(y);
        rotate(x);
    }
}
void access(int x)
{
    int y = 0;
    while(x)
    {
        splay(x);
        sx[x]+=s[ch[x][1]];
        sx[x]-=s[y];
        ch[x][1]=y;
        update(x);
        y=x,x=fa[x];
    }
}
void mtr(int x)
{
    access(x);
    splay(x);
    reser(x);
}
void split(int x,int y)
{
    mtr(x);
    access(y);
    splay(y);
}
void link(int x,int y)
{
    split(x,y);
    fa[x]=y;
    sx[y]+=s[x];
    update(y);
}
int findrt(int x)
{
    if(rt[x]==x)return x;
    return rt[x]=findrt(rt[x]);
}
int getfa(int x)
{
    int goal = s[x]>>1,tip = (s[x]&1);
    int ls = 0,rs = 0,ret = 0x7fffffff,vl,vr;
    while(x)
    {
        pushdown(x);
        vl = s[ch[x][0]]+ls;
        vr = s[ch[x][1]]+rs;
        if(vl<=goal&&vr<=goal)
        {
            if(tip){ret=x;break;}
            else if(ret>x)ret=x;
        }
        if(vl>vr)
        {
            rs += s[ch[x][1]]+sx[x]+1;
            x = ch[x][0];
        }else
        {
            ls += s[ch[x][0]]+sx[x]+1;
            x = ch[x][1];
        }
    }
    splay(ret);
    return ret;
}
int main()
{
    scanf("%d%d",&n,&m); 
    for(int i=1;i<=n;i++)
    {
        s[i]=1;
        sr^=i;
        rt[i]=i;
    }
    int u,v;
    char sc[10];
    for(int i=1;i<=m;i++)
    {
        scanf("%s",sc);
        if(sc[0]=='X')
        {
            printf("%d\n",sr);
        }else if(sc[0]=='Q')
        {
            scanf("%d",&u);
            printf("%d\n",findrt(u));
        }else
        {
            scanf("%d%d",&u,&v);
            link(u,v);
            u=findrt(u),v=findrt(v);
            split(u,v);//v=rt
            int r = getfa(v);
            sr = sr^u^v^r;
            rt[u] = rt[v] = rt[r] = r;
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/LiGuanlin1124/p/9649796.html