• [HNOI2012] 永无乡 解题报告 (splay+启发式合并)


    题目链接:https://www.luogu.org/problemnew/show/P3224#sub

    题目:

    题目大意:

    维护多个联通块,没有删除操作,每次询问某一联通块的第k大

    解法:

    维护联通块我们用并查集,询问第k大用splay,合并的时候splay暴力启发式合并就是了

    启发式合并:把size小的splay合并到size大的splay上,暴力插入就好了

    这道题的具体做法就是我们记录rt数组表示每个点的splay的根,在每次连边的时候就是把一方的根的所有节点全部插入到另一方的根去

    其他的可以参考我在洛谷的博客里写的东西:https://www.luogu.org/blog/xxzh2425/solution-p3224

    AC代码如下:

    // luogu-judger-enable-o2
    #include<iostream>
    #include<cstring>
    #include<cstdio>
    #include<algorithm>
    #include<queue>
    #include<cctype>
    #include<cstdlib>
    #define ri register int
    using namespace std;
    
    const int N=1e5+15;
    int n,m;
    int f[N],rt[N],w[N],fa[N];
    std::queue <int> dl;
    struct Splay
    {
        int ch[2];
        int ff,size;
    }t[N];
    inline int read()
    {
        char ch=getchar();
        int s=0,f=1;
        while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
        while (ch>='0'&&ch<='9') {s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
        return s*f;
    }
    inline int find(int x)
    {
        if (fa[x]!=x) fa[x]=find(fa[x]);
        return fa[x];
    }
    inline void pushup(int x)
    {
        t[x].size=t[t[x].ch[0]].size+t[t[x].ch[1]].size+1;
    }
    inline void rotate(int x)
    {
        int y=t[x].ff;
        int z=t[y].ff;
        int k=t[y].ch[1]==x;
        t[z].ch[t[z].ch[1]==y]=x;
        t[x].ff=z;
        t[y].ch[k]=t[x].ch[k^1];
        t[t[x].ch[k^1]].ff=y;
        t[x].ch[k^1]=y;
        t[y].ff=x;
        pushup(y);pushup(x);
    }
    inline void splay(int x,int goal)
    {
        while (t[x].ff!=goal)
        {
            int y=t[x].ff,z=t[y].ff;
            if (z!=goal) (t[y].ch[0]==x)^(t[z].ch[0]==y)?rotate(x):rotate(y);
            rotate(x);
        }
    }
    inline void insert(int x,int &now,int fat)
    {
        if (!now)
        {
            now=x;
            t[x].ff=fat;
            return;
        }
        t[now].ff=fat;
        t[now].size++;
        if (w[x]<=w[now]) insert(x,t[now].ch[0],now);
        else insert(x,t[now].ch[1],now);
    }
    inline void mergy(int x,int y)
    {
        if (x==y) return;
        if (t[rt[x]].size>t[rt[y]].size) std::swap(x,y);
        fa[rt[x]]=rt[y];
        dl.push(rt[x]);
        while (!dl.empty())
        {
            int k=dl.front();
            dl.pop();
            if (t[k].ch[0]) dl.push(t[k].ch[0]);
            if (t[k].ch[1]) dl.push(t[k].ch[1]);
            insert(k,rt[y],0);
            rt[k]=rt[y];
            //splay(k,rt[y]);
        }
    }
    inline int kth(int x,int k)
    {
        int now=rt[x];
        if (t[now].size<k) return -1;
        while (921)
        {
            if (t[t[now].ch[0]].size>=k) now=t[now].ch[0];
            else if (t[t[now].ch[0]].size+1==k) return now;
            else k-=t[t[now].ch[0]].size+1,now=t[now].ch[1];
        }
    }
    inline void write(int x)
    {
         if(x<0) putchar('-'),x=-x;
         if(x>9) write(x/10);
         putchar(x%10+'0');
    }
    int main()
    {
        n=read();m=read();
        for (ri i=1;i<=n;i++) 
        {
            w[i]=read();
            rt[i]=i;fa[i]=i;t[i].size=1;
        }
        for (ri i=1;i<=m;i++)
        {
            int u=read(),v=read();
            mergy(u,v);
        }
        int q=read();
        while (q--)
        {
            char ch=getchar();
            while (!(ch=='Q'||ch=='B')) ch=getchar();
            int x=read(),y=read();
            if (ch=='Q')
            {
                int ans=kth(find(x),y);
                write(ans);putchar('
    ');
            }
            else 
            {
                mergy(find(x),find(y));
            }
        }
        return 0;
    }

    诚恳地建议:

    去看看我在洛谷博客里写的东西

  • 相关阅读:
    Weblogic魔法堂:AdminServer.lok被锁导致启动、关闭域失败
    CSS魔法堂:盒子模型简介
    .Net魔法堂:提取注释生成API文档
    CSS魔法堂:Position定位详解
    CMD魔法堂:获取进程路径和PID值的方法集
    CentOS6.5菜鸟之旅:识别NTFS分区
    CentOS6.5菜鸟之旅:安装rpmforge软件库
    CMD魔法堂:CMD进入指定目录
    CentOS6.5菜鸟之旅:VIM插件NERDtree初探
    CSS魔法堂:选择器及其优先级
  • 原文地址:https://www.cnblogs.com/xxzh/p/9571249.html
Copyright © 2020-2023  润新知