#ifndef RANDOMIZED_BINARY_SEARCH_TREE
#define RANDOMIZED_BINARY_SEARCH_TREE
template<typename T>
class random_bst{
	private:
		struct node{
			T data;
			unsigned s;
			node *ch[2];
			node(const T&d):data(d),s(1){}
			node():s(0){ch[0]=ch[1]=this;}
		}*nil,*root;
		unsigned x;
		inline unsigned ran(){
			return x=x*0xdefaced+1;
		}
		inline void rotate(node *&a,bool d){
			node *b=a;
			a=a->ch[!d];
			a->s=b->s;
			b->ch[!d]=a->ch[d];
			a->ch[d]=b;
			b->s=b->ch[0]->s+b->ch[1]->s+1;
		}
		void insert_as_root(node *&p,const T &data){
			if(!p->s){
				p=new node(data);
				p->ch[0]=p->ch[1]=nil;
			}else{
				++p->s;
				insert_as_root(p->ch[p->data<data],data);
				rotate(p,!(p->data<data));
			}
		}
		void insert(node *&p,const T &data){
			if(ran()%(p->s+1)==0){
				insert_as_root(p,data);
			}else{
				++p->s;
				insert(p->ch[p->data<data],data);
			}
		}
		bool erase(node *&o,const T &data){
			if(!o->s)return 0;
			if(o->data==data){
				if(!o->ch[0]->s||!o->ch[1]->s){
					node *t=o;
					o=o->ch[0]->s?o->ch[0]:o->ch[1];
					delete t;
				}else{
					--o->s;
					bool d=ran()%(o->ch[0]->s+o->ch[1]->s)<o->ch[0]->s;
					rotate(o,d);
					erase(o->ch[d],data);
				}
				return 1;
			}else if(erase(o->ch[o->data<data],data)){
				--o->s;return 1;
			}else return 0;
		}
		void clear(node *&o){
			if(o->s)clear(o->ch[0]),clear(o->ch[1]),delete o;
		}
	public:
		random_bst(unsigned s=20150112):nil(new node),root(nil),x(s){}
		~random_bst(){clear(root),delete nil;}
		inline void clear(){clear(root),root=nil;}
		inline void insert(const T &data){
			insert(root,data);
		}
		inline bool erase(const T &data){
			return erase(root,data);
		}
		inline bool find(const T&data){
			for(node *o=root;o->s;)
			if(o->data==data)return 1;
			else o=o->ch[o->data<data];
			return 0;
		}
		inline int rank(const T&data){
			int cnt=0;
			for(node *o=root;o->s;)
			if(o->data<data)cnt+=o->ch[0]->s+1,o=o->ch[1];
			else o=o->ch[0];
			return cnt;
		}
		inline const T&kth(int k){
			for(node *o=root;;)
			if(k<=o->ch[0]->s)o=o->ch[0];
			else if(k==o->ch[0]->s+1)return o->data;
			else k-=o->ch[0]->s+1,o=o->ch[1];
		}
		inline const T&operator[](int k){
			return kth(k);
		}
		inline const T&preorder(const T&data){
			node *x=root,*y=0;
			while(x->s)
			if(x->data<data)y=x,x=x->ch[1];
			else x=x->ch[0];
			if(y)return y->data;
			return data;
		}
		inline const T&successor(const T&data){
			node *x=root,*y=0;
			while(x->s)
			if(data<x->data)y=x,x=x->ch[0];
			else x=x->ch[1];
			if(y)return y->data;
			return data;
		}
		inline int size(){return root->s;}
};
#endif