• BZOJ3224 洛谷3369 Tyvj 1728 普通平衡树 splay


    欢迎访问~原文出处——博客园-zhouzhendong

    去博客园看该题解


    题目传送门 - BZOJ3224


    题意概括

      您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
    1. 插入x数
    2. 删除x数(若有多个相同的数,因只删除一个)
    3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
    4. 查询排名为x的数
    5. 求x的前驱(前驱定义为小于x,且最大的数)
    6. 求x的后继(后继定义为大于x,且最小的数)


    题解

      splay模板题。

      


    代码

     UPD(2018-03-20):省选一试前夜,抱佛脚打板子,发现之前的代码真丑。注意,在splay中预先放一个非常大的数可以有效的排除平衡树空的特殊情况。我在细节处理上也增加了大量改进,代码量爆缩,运行效率略高了一些,老的那份代码在后面。

    #include <bits/stdc++.h>
    using namespace std;
    const int N=100005;
    int n,root=1,size=1,val[N],cnt[N],son[N][2],fa[N],tot[N];
    int wson(int x){
    	return son[fa[x]][1]==x;
    }
    void pushup(int x){
    	tot[x]=cnt[x]+tot[son[x][0]]+tot[son[x][1]];
    }
    void rotate(int x){
    	if (!x)
    		return;
    	int y=fa[x],z=fa[y],L=wson(x),R=L^1;
    	if (z)
    		son[z][wson(y)]=x;
    	fa[x]=z,fa[y]=x,fa[son[x][R]]=y;
    	son[y][L]=son[x][R],son[x][R]=y;
    	pushup(y),pushup(x);
    }
    void splay(int x,int k){
    	if (!x)
    		return;
    	if (!k)
    		root=x;
    	for (int y=fa[x];fa[x]!=k;rotate(x),y=fa[x])
    		if (fa[y]!=k)
    			rotate(wson(x)==wson(y)?y:x);
    }
    int find(int x,int v){
    	return val[x]==v?x:find(son[x][v>val[x]],v);
    }
    int findkth(int x,int k){
    	if (k<=tot[son[x][0]])
    		return findkth(son[x][0],k);
    	k-=tot[son[x][0]];
    	if (k<=cnt[x])
    		return x;
    	k-=cnt[x];
    	return findkth(son[x][1],k);
    }
    int findnxt(int x,int v){
    	if (!x)
    		return 0;
    	if (val[x]<=v)
    		return findnxt(son[x][1],v);
    	else {
    		int res=findnxt(son[x][0],v);
    		return res?res:x;
    	}
    }
    int findpre(int x,int v){
    	if (!x)
    		return 0;
    	if (val[x]>=v)
    		return findpre(son[x][0],v);
    	else {
    		int res=findpre(son[x][1],v);
    		return res?res:x;
    	}
    }
    void insert(int &x,int pre,int v){
    	if (!x){
    		x=++size;
    		val[x]=v,cnt[x]=tot[x]=1,fa[x]=pre;
    		splay(x,0);
    		return;
    	}
    	tot[x]++;
    	if (val[x]==v){
    		cnt[x]++;
    		return;
    	}
    	insert(son[x][v>val[x]],x,v);
    }
    void Insert(int v){insert(root,0,v);}
    void Delete(int v){
    	int x;
    	splay(x=find(root,v),0);
    	if (--cnt[x])
    		return;
    	splay(findnxt(root,v),root);
    	root=son[x][1];
    	son[root][0]=son[x][0];
    	fa[son[x][0]]=root;
    	fa[root]=son[x][0]=son[x][1]=0;
    	pushup(root);
    }
    int Rank(int v){
    	splay(find(root,v),0);
    	return tot[son[root][0]]+1;
    }
    int main(){
    	val[1]=2147483647;
    	cnt[1]=tot[1]=1;
    	scanf("%d",&n);
    	while (n--){
    		int opt,x;
    		scanf("%d%d",&opt,&x);
    		if (opt==1) Insert(x);
    		if (opt==2) Delete(x);
    		if (opt==3) printf("%d
    ",Rank(x));
    		if (opt==4) printf("%d
    ",val[findkth(root,x)]);
    		if (opt==5) printf("%d
    ",val[findpre(root,x)]);
    		if (opt==6) printf("%d
    ",val[findnxt(root,x)]);
    	}
    	return 0;
    }
    

      

    #include <cstring>
    #include <algorithm>
    #include <cstdio>
    #include <cmath>
    #include <cstdlib>
    using namespace std;
    const int N=100005;
    struct Splay{
    	int fa[N],lc[N],rc[N],size[N],cnt[N],val[N],root,tot;
    	void clear(){//splay³õʼ»¯ 
    		root=tot=0,memset(size,0,sizeof size),memset(cnt,0,sizeof cnt);
    	}
    	void update(int x){//¼ÆËã(¸üÐÂ)ijһ¸ö½ÚµãµÄsize 
    		if (x){
    			size[x]=cnt[x];
    			size[x]+=lc[x]?size[lc[x]]:0;
    			size[x]+=rc[x]?size[rc[x]]:0;
    		}
    	}
    	void zig(int x){//ÓÒÐý 
    		if (!fa[x])
    			return;
    		int y=fa[x],z=fa[y];
    		if (z)
    			if (lc[z]==y)
    				lc[z]=x;
    			else
    				rc[z]=x;
    		fa[x]=z;
    		fa[y]=x;
    		fa[rc[x]]=y;
    		lc[y]=rc[x];
    		rc[x]=y;
    		update(y);
    		update(x);
    	}
    	void zag(int x){//×óÐý 
    		if (!fa[x])
    			return;
    		int y=fa[x],z=fa[y];
    		if (z)
    			if (lc[z]==y)
    				lc[z]=x;
    			else
    				rc[z]=x;
    		fa[x]=z;
    		fa[y]=x;
    		fa[lc[x]]=y;
    		rc[y]=lc[x];
    		lc[x]=y;
    		update(y);
    		update(x);
    	}
    	void splay(int rt,int x){//splayÖ÷¹ý³Ì(ÔÚÒÔrtΪ¸ùµÄ×ÓÊ÷ÖÐsplay£¬×îÖÕx³ÉΪµ±Ç°×ÓÊ÷µÄÐÂ×æ×Ú)
    		rt=fa[rt];
    		int y,z;
    		while (fa[x]!=rt){
    			y=fa[x];
    			z=fa[y];
    			if (z&&z!=rt){
    				if (lc[z]==y&&lc[y]==x)
    					zig(y),zig(x);
    				else if (lc[z]==y&&rc[y]==x)
    					zag(x),zig(x);
    				else if (rc[z]==y&&lc[y]==x)
    					zig(x),zag(x);
    				else
    					zag(y),zag(x);
    			}
    			else if (lc[y]==x)
    				zig(x);
    			else
    				zag(x);
    		}
    		if (!fa[x])
    			root=x;
    	}
    	void splay(int x){
    		splay(root,x);
    	}
    	void ins(int &k,int key,int p){//ÔÚkÕâ¸ö×ÓÊ÷ÖвåÈëֵΪkeyµÄÊý£¬µ±Ç°½ÚµãµÄ¸¸Ç×Ϊp 
    		if (!k){
    			size[k=++tot]=cnt[k]=1;
    			lc[k]=rc[k]=0;
    			val[k]=key;
    			fa[k]=p;
    			splay(k);
    			return;
    		}
    		size[k]++;
    		if (key==val[k]){
    			cnt[k]++;
    			return;
    		}
    		if (key<val[k])
    			ins(lc[k],key,k);
    		else
    			ins(rc[k],key,k);
    	}
    	void ins(int key){//ÔÚÕû¸ösplayÀïÃæ²åÈëָΪkeyµÄÊý 
    		if (!root){
    			size[root=++tot]=cnt[root]=1;
    			lc[root]=rc[root]=0;
    			val[root]=key;
    			fa[root]=0;
    			return;
    		}
    		ins(root,key,0);
    	}
    	int find(int k,int key){//ÔÚÒÔkΪ¸ùµÄsplayÀïÃæ²éÕÒֵΪkeyµÄÊýµÄ´æ´¢±àºÅ  
    		int tmp=k;
    		while (k)
    			if (val[k]==key)
    				break;
    			else
    				k=key<val[k]?lc[k]:rc[k];
    		if (k)
    			splay(k);
    		return k;
    	}
    	int find(int key){//splayÀïÃæ²éÕÒֵΪkeyµÄÊýµÄ´æ´¢±àºÅ  
    		return find(root,key);
    	}
    	void del(int key){//ɾ³ýֵΪkeyµÄÊý£¨µ«ÊÇtot²»¼õ£¬Òâζ×ÅÓÐ1¸ö¿Õ¼ä»áÀË·Ñ£© 
    		int x=find(key),ls=lc[x],rs=rc[x];
    		if (!x)
    			return;
    		if (--cnt[x])
    			return;
    		if (!ls&&!rs){
    			clear();
    			return;
    		}
    		if (!ls)
    			root=rs,fa[rs]=0;
    		else if (!rs)
    			root=ls,fa[ls]=0;
    		else {
    			int lson=getmax(ls);
    			swap(lson,ls);
    			fa[lson]=0;
    			splay(ls);
    			rc[ls]=rs;
    			fa[rs]=ls;
    			update(ls);
    		}
    	}
    	int getmin(int k){//ÔÚ¸ùΪkµÄsplayÖÐÕÒ×îСֵµÄ´æ´¢±àºÅ 
    		return lc[k]?getmin(lc[k]):k;
    	}
    	int getmax(int k){//ÔÚ¸ùΪkµÄsplayÖÐÕÒ×î´óÖµµÄ´æ´¢±àºÅ 
    		return rc[k]?getmax(rc[k]):k;
    	}
    	int findkth(int k){//Ñ°ÕÒµÚkСµÄ 
    		int t=root;
    		while (t){
    			if (size[lc[t]]<k&&k<=size[lc[t]]+cnt[t])
    				break;
    			if (k<=size[lc[t]])
    				t=lc[t];
    			else
    				k-=size[lc[t]]+cnt[t],t=rc[t];
    		}
    		splay(t);
    		return t;
    	}
    	int findpre(int k,int key){//ÔÚ¸ùΪkµÄsplayÖÐÕÒkeyµÄÇ°Çý£¨¼´Öµ<keyµÄ×î´óÖµ£©µÄ´æ´¢±àºÅ 
    		if (!k)
    			return 0;
    		if (key<=val[k])
    			return findpre(lc[k],key);
    		else {
    			int tmp=findpre(rc[k],key);
    			return tmp?tmp:k;
    		}
    	}
    	int findpre(int key){return findpre(root,key);}//ÕÒkeyµÄÇ°Çý£¨¼´Öµ<keyµÄ×î´óÖµ£©µÄ´æ´¢±àºÅ 
    	int findnxt(int k,int key){//ÔÚ¸ùΪkµÄsplayÖÐÕÒkeyµÄºó¼Ì£¨¼´Öµ>keyµÄ×îСֵ£©µÄ´æ´¢±àºÅ 
    		if (!k)
    			return 0;
    		if (key>=val[k])
    			return findnxt(rc[k],key);
    		else {
    			int tmp=findnxt(lc[k],key);
    			return tmp?tmp:k;
    		}
    	}
    	int findnxt(int key){return findnxt(root,key);}//ÕÒkeyµÄºó¼Ì£¨¼´Öµ>keyµÄ×îСֵ£©µÄ´æ´¢±àºÅ 
    }s;
    int n,opt,x;
    int main(){
    	scanf("%d",&n);
    	s.clear();
    	for (int i=1;i<=n;i++){
    		scanf("%d%d",&opt,&x);
    		if (opt==1)	s.ins(x);
    		if (opt==2)	s.del(x);
    		if (opt==3){//ÇóֵΪxµÄÃû´Î 
    			s.splay(s.find(x));
    			printf("%d
    ",s.size[s.lc[s.root]]+1);
    		}
    		if (opt==4)	printf("%d
    ",s.val[s.findkth(x)]);
    		if (opt==5)	printf("%d
    ",s.val[s.findpre(x)]);
    		if (opt==6)	printf("%d
    ",s.val[s.findnxt(x)]);
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    MyBatis学习笔记
    【Ts 5】Httpclient的应用和封装
    【drp 12】再识转发和重定向:SpringMVC无法跳转页面
    【多线程 5】线程池的类型以及submit()和execute()的区别
    【多线程 5】线程池的类型以及submit()和execute()的区别
    【多线程 4】多线程实例(实例分析博客在下一篇)
    【多线程 4】多线程实例(实例分析博客在下一篇)
    【多线程 3】多线程间的变量共享方式
    【多线程 3】多线程间的变量共享方式
    【多线程 2】常见的多线程创建方式
  • 原文地址:https://www.cnblogs.com/zhouzhendong/p/BZOJ3224.html
Copyright © 2020-2023  润新知