zoukankan      html  css  js  c++  java
  • [洛谷P3369]【模板】普通平衡树(Treap/SBT)

    题目大意:给你一些操作:

    1.插入一个数;

    2.删除一个数;

    3.输出x是第几小的数;

    4.输出第k小的数是几;

    5.输出比x小的最大数;

    6.输出比x大的最小数。

    要你实现它。

    解题思路:平衡树模板题。

    用Treap/Splay/替罪羊树/pbds(雾)等均可。

    我使用简单的Treap实现。

    注意在5和6操作时,必须要搜到叶子才停止,否则会遗漏答案。

    这里用指针实现,删除操作可能会出现内存浪费。

    C++ Code:

    #include<cstdio>
    #include<cctype>
    #include<ctime>
    #include<cstdlib>
    class treap{
    	private:
    		struct node{
    			node* ch[2];
    			int s,x,r,sz;
    			node(){
    				ch[0]=ch[1]=NULL;
    			}
    		};
    		void update(node*&o){
    			o->s=o->sz;
    			if(o->ch[0]!=NULL)o->s+=o->ch[0]->s;
    			if(o->ch[1]!=NULL)o->s+=o->ch[1]->s;
    		}
    		void rotate(node*& o,int d){
    			node* k=o->ch[d^1];
    			o->ch[d^1]=k->ch[d];
    			k->ch[d]=o;
    			update(o);
    			update(k);
    			o=k;
    		}
    	public:
    		node* rt;
    		void ins(node*&o,int p){
    			if(o==NULL){
    				o=new node;
    				o->s=o->sz=1;
    				o->x=p;
    				o->r=rand();
    				return;
    			}
    			if(p<o->x){
    				ins(o->ch[0],p);
    				if(o->ch[0]->r<o->r)rotate(o,1);
    			}else
    			if(p>o->x){
    				ins(o->ch[1],p);
    				if(o->ch[1]->r<o->r)rotate(o,0);
    			}else ++o->sz;
    			update(o);
    		}
    		void del(node*&o,int p){
    			if(o==NULL)return;
    			if(o->x==p){
    				if(o->sz>1)--o->sz;else
    				if(o->ch[0]==NULL&&o->ch[1]==NULL)o=NULL;else
    				if(o->ch[0]!=NULL&&o->ch[1]!=NULL){
    					if(o->ch[0]->r<o->ch[1]->r){
    						rotate(o,1);
    						del(o->ch[1],p);
    					}else{
    						rotate(o,0);
    						del(o->ch[0],p);
    					}
    				}else
    				if(o->ch[0]==NULL)o=o->ch[1];else o=o->ch[0];
    				if(o!=NULL)update(o);
    			}else{
    				if(p<o->x)del(o->ch[0],p);else del(o->ch[1],p);
    				if(o!=NULL)update(o);
    			}
    		}
    		int find(node* o,int p){
    			if(o==NULL)return 0;
    			int l=0;
    			if(o->ch[0]!=NULL)l=o->ch[0]->s;
    			if(o->x==p)return l+1;
    			if(o->x>p)return find(o->ch[0],p);
    			return l+o->sz+find(o->ch[1],p);
    		}
    		int kth(node* o,int k){
    			if(o==NULL)return 0;
    			int l=0;
    			if(o->ch[0]!=NULL)l=o->ch[0]->s;
    			if(k>l&&k<=l+o->sz)return o->x;
    			if(k<=l)return kth(o->ch[0],k);
    			return kth(o->ch[1],k-l-o->sz);
    		}
    		void pre(node* o,int p,int& ans){
    			if(o==NULL)return;
    			if(o->x<p){
    				if(ans<o->x)ans=o->x;
    				if(o->ch[1]!=NULL)pre(o->ch[1],p,ans);
    			}else
    			if(o->ch[0]!=NULL)pre(o->ch[0],p,ans);
    		}
    		void nxt(node* o,int p,int& ans){
    			if(o==NULL)return;
    			if(o->x>p){
    				if(ans>o->x)ans=o->x;
    				if(o->ch[0]!=NULL)nxt(o->ch[0],p,ans);
    			}else
    			if(o->ch[1]!=NULL)nxt(o->ch[1],p,ans);
    		}
    		treap(){rt=NULL;}
    }Treap;
    inline int readint(){
    	char c=getchar();
    	bool b=false;
    	for(;!isdigit(c);c=getchar())b=c=='-';
    	int d=0;
    	for(;isdigit(c);c=getchar())
    	d=(d<<3)+(d<<1)+(c^'0');
    	return b?-d:d;
    }
    int main(){
    	srand(2333);
    	for(int n=readint();n--;){
    		int opt=readint(),x=readint();
    		if(opt==1)Treap.ins(Treap.rt,x);else
    		if(opt==2)Treap.del(Treap.rt,x);else
    		if(opt==3)printf("%d
    ",Treap.find(Treap.rt,x));else
    		if(opt==4)printf("%d
    ",Treap.kth(Treap.rt,x));else
    		if(opt==5){
    			int ans=-2000000000;
    			Treap.pre(Treap.rt,x,ans);
    			printf("%d
    ",ans);
    		}else{
    			int ans=2000000000;
    			Treap.nxt(Treap.rt,x,ans);
    			printf("%d
    ",ans);
    		}
    	}
    	return 0;
    }
  • 相关阅读:
    [转]SVN服务器搭建和使用(二)
    [转]SVN服务器搭建和使用(一)
    BZOJ 2049 Sdoi2008 Cave 洞穴勘测
    BZOJ 1589 Usaco2008 Dec Trick or Treat on the Farm 采集糖果
    BZOJ 2796 POI2012 Fibonacci Representation
    BZOJ 2115 Wc2011 Xor
    BZOJ 3105 CQOI2013 新Nim游戏
    BZOJ 2460 Beijing2011 元素
    BZOJ 3687 简单题
    BZOJ 1068 SCOI2008 压缩
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/8444135.html
Copyright © 2011-2022 走看看