zoukankan      html  css  js  c++  java
  • 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
    ",sr);
            }else if(sc[0]=='Q')
            {
                scanf("%d",&u);
                printf("%d
    ",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;
    }
  • 相关阅读:
    CodeForces Gym 100935G Board Game DFS
    CodeForces 493D Vasya and Chess 简单博弈
    CodeForces Gym 100935D Enormous Carpet 快速幂取模
    CodeForces Gym 100935E Pairs
    CodeForces Gym 100935C OCR (水
    CodeForces Gym 100935B Weird Cryptography
    HDU-敌兵布阵
    HDU-Minimum Inversion Number(最小逆序数)
    七月馒头
    非常可乐
  • 原文地址:https://www.cnblogs.com/LiGuanlin1124/p/9649796.html
Copyright © 2011-2022 走看看