zoukankan      html  css  js  c++  java
  • [Luogu 3224] HNOI2012 永无乡

    [Luogu 3224] HNOI2012 永无乡

    <题目链接>


    特别水一个平衡树题。

    不认真的代价是调试时间指数增长。

    我写的 SBT,因为 Treap 的 rand() 实在写够了。

    用并查集维护这些点的关系,然后启发式暴力合并,以及找第 (k) 小。

    就是把子树较小的并到较大的里,一个一个点插入。

    因为要插入新的点,给 SBT 预留的空间要大一些。(我试过只改变原来的点的信息,结果失败了。)

    SBT 需要开的空间为 (MAXN+MAXM),因为 (n) 个点,每个点最多被插入 (m) 次。

    就这样。

    表白一万次 SBT 的 Maintain 操作代码,超优美的qwq。

    #include <algorithm>
    #include <cstdio>
    #include <cstring>
    using std::swap;
    const int MAXN=100010,MAXM=400010;
    int n,m,q;
    class UFS
    {
    	public:
    		void Init(int i)
    		{
    			f[i]=i;
    		}
    		int Find(int x)
    		{
    			return x==f[x] ? f[x] : f[x]=Find(f[x]);
    		}
    		void Merge(int x,int y)
    		{
    			f[Find(y)]=Find(x);
    		}
    	private:
    		int f[MAXN];
    }S;
    class SBT
    {
    	public:
    		SBT(int cnt=0):cnt(cnt){}
    		void Init(void)
    		{
    			for(int i=1,x;i<=n;++i)
    			{
    				scanf("%d",&x);
    				S.Init(i),s[rt[i]=++cnt]=node(x,i,1);
    			}
    		}
    		void Bridge(int x,int y)
    		{
    			int a=S.Find(x),b=S.Find(y);
    			if(a==b)
    				return;
    			if(s[rt[a]].size>s[rt[b]].size)
    				S.Merge(a,b),Merge(rt[a],b);
    			else
    				S.Merge(b,a),Merge(rt[b],a);
    		}
    		int FindKth(int x,int k)
    		{
    			return k>s[x=rt[S.Find(x)]].size ? -1 : Find(x,k);
    		}
    	private:
    		int cnt,rt[MAXN];
    		struct node
    		{
    			int v,num,size,c[2];
    			node(int v=0,int num=0,int size=0):v(v),num(num),size(size)
    			{
    				memset(c,0,sizeof c);
    			}
    		}s[MAXM];
    		void Update(int i)
    		{
    			s[i].size=s[s[i].c[0]].size+s[s[i].c[1]].size+1;
    		}
    		void Rotate(int &i,bool p)
    		{
    			int t=s[i].c[!p];
    			s[i].c[!p]=s[t].c[p],s[t].c[p]=i;
    			Update(i),Update(i=t);
    		}
    		void Maintain(int &i,bool p)
    		{
    			int t=s[s[i].c[!p]].size;
    			if(t<s[s[s[i].c[p]].c[p]].size)
    				Rotate(i,!p);
    			else if(t<s[s[s[i].c[p]].c[!p]].size)
    				Rotate(s[i].c[p],p),Rotate(i,!p);
    			else
    				return;
    			Maintain(s[i].c[0],0),Maintain(s[i].c[1],1),Maintain(i,0),Maintain(i,1);
    		}
    		void Insert(int &i,int x,int num)
    		{
    			if(!i)
    			{
    				s[i=++cnt]=node(x,num,1);
    				return;
    			}
    			++s[i].size;
    			bool t=x>s[i].v;
    			Insert(s[i].c[t],x,num);
    			Maintain(i,t);
    		}
    		void Merge(int &x,int &y)
    		{
    			if(!y)
    				return;
    			Insert(x,s[y].v,s[y].num),Merge(x,s[y].c[0]),Merge(x,s[y].c[1]);
    		}
    		int Find(int i,int x)
    		{
    			int t;
    			while(x!=(t=s[s[i].c[0]].size+1))
    				if(x<t)
    					i=s[i].c[0];
    				else
    					x-=t,i=s[i].c[1];
    			return s[i].num;
    		}
    }T;
    int main(int argc,char *argv[])
    {
    	scanf("%d %d",&n,&m);
    	T.Init();
    	for(int i=1,x,y;i<=m;++i)
    	{
    		scanf("%d %d",&x,&y);
    		T.Bridge(x,y);
    	}
    	scanf("%d",&q);
    	for(int i=1,x,y;i<=q;++i)
    	{
    		char c;
    		scanf("
    %c %d %d",&c,&x,&y);
    		if(c=='B')
    			T.Bridge(x,y);
    		else
    			printf("%d
    ",T.FindKth(x,y));
    	}
    	return 0;
    }
    

    谢谢阅读。

  • 相关阅读:
    PHP学习—Cookie&Session
    IP组播综合实验
    k8s kubeadm部署高可用集群
    python调用zbbix的api实现批量添加域名监控脚本
    Python调用Harbor api删除私有仓库harbor镜像
    Kubernetes故障排查指南-分析容器退出状态码
    blackbox_exporter+grafana+prometheus监控主机存活,端口存活及网站状态
    k8s中使用ceph-csi在ceph中进行数据持久化
    Jenkins+K8S流水线自动化部署Java程序
    生产环境k8s中使用helm部署prometheus+grafana监控k8s集群中相关node和pod
  • 原文地址:https://www.cnblogs.com/Capella/p/8562841.html
Copyright © 2011-2022 走看看