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;
    }
  • 相关阅读:
    无线传感网3-1.目标物的覆盖技术
    无线传感网2-传感器布局方法
    JAVA 第二周课程总结
    2019春总结作业
    第十二周作业
    第十一周作业
    第十周
    第九周作业
    第八周作业
    第七周作业
  • 原文地址:https://www.cnblogs.com/Mrsrz/p/8444135.html
Copyright © 2011-2022 走看看