[Tyvj 1728]普通平衡树 5种姿势 (彩蛋)

经典裸题。

对于Treap来说无旋Treap常数较大,但是可以支持快速的合并和分裂(对splay无再爱)

打颗无旋Treap就好了。

无旋Treap:

#define MAXN 100005
#include <bits/stdc++.h>
using namespace std;
int n;
 
 
struct node{
	int v,r,s;
	node *ch[2];
	
	void Maintain(){
		s=ch[0]->s+ch[1]->s+1;
	}
 
	void *operator new (size_t);
 
	node(){
		v=r=s=0;
		ch[0]=ch[1]=NULL;
	}
 
	node(int x);
}*null=new node(),*C,*mempool;
 
void* node :: operator new (size_t){
	if(C==mempool){
		C=new node[1<<15];
		mempool=C+(1<<15);
	}
	return C++;
}
 
node :: node(int x){
	v=x;s=1;r=rand();
	ch[0]=ch[1]=null;
}
 
typedef pair<node*,node*> pa;
 
class Treap{
	private:
		node *root;
	public:
		Treap(){
			root = null;
		}
		pa spilt(node *o,int k){
			if(o==null)return make_pair(null,null);
			if(k<=o->ch[0]->s){
				pa y = spilt(o->ch[0],k);
				o->ch[0] = y.second;
				o->Maintain();
				y.second=o;
				return y;
			}
			else{
				pa y = spilt(o->ch[1],k-o->ch[0]->s-1);
				o->ch[1] = y.first;
				o->Maintain();
				y.first=o;
				return y;
			}
		}
 
		node *merge(node *a,node *b){
			if(a==null)return b;
			if(b==null)return a;
			if(a->r>b->r){
				a->ch[1]=merge(a->ch[1],b);
				a->Maintain();
				return a;
			}
			else{
				b->ch[0]=merge(a,b->ch[0]);
				b->Maintain();
				return b;
			}
		}
 
		inline int Rank(int x){
			node *o=root;
			int ans=0;
			while(o!=null){
				if(x<=o->v)o=o->ch[0];
				else ans+=o->ch[0]->s+1,o=o->ch[1];
			}
			return ans;
		}
 
		inline void insert(int val){
			int k = Rank(val);
			pa x = spilt(root,k);
			node *p=new node(val);
			root=merge(merge(x.first,p),x.second);
		}
 
		inline void erase(int val){
			int k = Rank(val);
			pa x = spilt(root,k);
			pa y = spilt(x.second,1);
			root = merge(x.first,y.second);
		}
 
		inline node* kth(int k){
			node *o = root;
			while(o!=null){
				if(k==o->ch[0]->s+1)return o;
				if(k<=o->ch[0]->s)o=o->ch[0];
				else k-=o->ch[0]->s+1,o=o->ch[1];
			}
			return null;
		}
}treap;
 
 
int main(){
	freopen("phs.in","r",stdin);
	freopen("phs.out","w",stdout);
	int q,opt,x;
	scanf("%d",&q);
	while(q--){
		scanf("%d%d", &opt, &x);
        switch (opt){
            case 1:treap.insert(x);break;
            case 2:treap.erase(x);break;
            case 3:printf("%d\n", treap.Rank(x)+1);break;
            case 4:printf("%d\n", treap.kth(x)->v);break;
            case 5:printf("%d\n", treap.kth(treap.Rank(x))->v);break;
			case 6:printf("%d\n", treap.kth(treap.Rank(x + 1)+1)->v);break;
        }
	}
}
Treap:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <cstdlib>
#define size(x) ((x) ? (x->s) : (0))
using namespace std;
const int maxn =1000005;
 
 
struct Node{
	int v,s,r;
	Node *ch[2];
	Node(int x){
		s=1;
		v=x;
		ch[0]=ch[1]=NULL;
		r=rand();
	}
	int cmp(int x)const{
		if(x==v)return -1;
		return x<v?0:1;
	}
	void Maintain(){
		s=1;
		if(ch[0]!=NULL)s+=ch[0]->s;
		if(ch[1]!=NULL)s+=ch[1]->s;
	}
}*root;
 
void rotate(Node* &o,int d){
	Node *k=o->ch[d^1];
	o->ch[d^1]=k->ch[d];
	k->ch[d]=o;
	o->Maintain();k->Maintain();
	o=k;
}
 
void insert(Node* &o,int x){
	if(o==NULL)o=new Node(x);
	else{
		int d=x< o->v?0:1;
		insert(o->ch[d],x);
		if(o->ch[d]->r > o->r)rotate(o,d^1);
	}
	o->Maintain();
}
 
int kth(Node *o,int k){
	if(o==NULL||k<=0||k>o->s)return -1;
	if(o->ch[0]==NULL&&k==1)return o->v;
	if(o->ch[0]==NULL)return kth(o->ch[1],k-1);
	if(o->ch[0]->s>=k)return kth(o->ch[0],k);
	if(o->ch[0]->s+1==k)return o->v;
	return kth(o->ch[1],k-1-o->ch[0]->s);
}
 
void del(Node* &o,int x){
	if(o==NULL)return;
	int d=o->cmp(x);
	if(d==-1){
		Node *tmp=o;
		if(o->ch[0]!=NULL&&o->ch[1]!=NULL){
			int k=o->ch[0]->r > o->ch[1]->r?1:0;
			rotate(o,k);
			del(o->ch[k],x);
		}
		else{
			if(o->ch[0]==NULL)o=o->ch[1];else o=o->ch[0];
			delete tmp;tmp=NULL;
		}
	}
	else del(o->ch[d],x);
	if(o!=NULL)o->Maintain();
}
 
int rank(Node *o,int x){
	int res=1;
	while(o){
		if(x>o->v)res+=size(o->ch[0])+1,o=o->ch[1];
		else o=o->ch[0];
	}
	return res;
}
 
int pre(Node *o,int x,int k){
	if(o==NULL)return k;
	if(x>o->v)return pre(o->ch[1],x,o->v);
	return pre(o->ch[0],x,k);
}
 
int next(Node *o,int x,int k){
	if(o==NULL)return k;
	if(x<o->v)return next(o->ch[0],x,o->v);
	return next(o->ch[1],x,k);
}
 
int n,m,x;  
 
int main(){
	srand(time(0));
	freopen("phs.in","r",stdin);
	freopen("phs.out","w",stdout);
	scanf("%d",&n);
	root=NULL;
	int cnt=0;
	while(n--){
		cnt++;
		int op,x;
		scanf("%d%d",&op,&x);
		switch(op){
			case 1:insert(root,x);break;
			case 2:del(root,x);break;
			case 3:printf("%d\n",rank(root,x));break;
			case 4:printf("%d\n",kth(root,x));break;
			case 5:printf("%d\n",pre(root,x,0));break;
			case 6:printf("%d\n",next(root,x,0));break;
		}
	}
	return 0;
}

01Trie

#include <stdio.h>
#include <cstring>
const int full = 1<<30;
const int fix = 10000000;
int n;
 
 
template<typename _t>
inline _t read(){
    _t x=0,f=1;
    char ch=getchar();
    for(;ch>'9'||ch<'0';ch=getchar())if(ch=='-')f=-f;
    for(;ch>='0'&&ch<='9';ch=getchar())x=x*10+(ch^48);
    return x*f;
}
 
struct node{
    node *ch[2];
    int sum;
    void* operator new(size_t);
}*null=new node,*C,*mempool,*root;
 
void* node :: operator new(size_t){
    if(C==mempool){
        C=new node[1<<15];
        mempool=C+(1<<15);
    }
    C->ch[0]=C->ch[1]=null;
    C->sum=0;
    return C++;
}
 
inline void insert(int x,int add){
    node *rt=root;x+=fix;
    for(int i=30;~i;i--){
        int d = x&(1<<i)?1:0;
        if(rt->ch[d]==null)rt->ch[d]=new node;
        rt=rt->ch[d];
        rt->sum+=add;
    }
}
 
int Rank(int x){
    x+=fix;int Ans=0;
    node *rt=root;
    for(int i=30;~i;i--){
        if(x&(1<<i))Ans+=rt->ch[0]->sum,rt=rt->ch[1];
        else rt=rt->ch[0];
    }
    return Ans+1;
}
 
inline int kth(int k){
    node *rt=root;
    int Ans=0;
    for(int i=30;~i;i--){
        if(k>rt->ch[0]->sum)Ans|=1<<i,k-=rt->ch[0]->sum,rt=rt->ch[1];
        else rt=rt->ch[0];
    }
    return Ans-fix;
}
 
int main(){
    null->ch[0]=null->ch[1]=null;
    root = new node;
    freopen("phs.in","r",stdin);
    freopen("phs.out","w",stdout);
    n=read<int>();
    while(n--){
        int op=read<int>(),x=read<int>();
        switch(op){
            case 1:insert(x,1);break;
            case 2:insert(x,-1);break;
            case 3:printf("%d\n",Rank(x));break;
            case 4:printf("%d\n",kth(x));break;
            case 5:printf("%d\n",kth(Rank(x)-1));break;
            case 6:printf("%d\n",kth(Rank(x+1)));break;
        }
    }
}



对替罪羊来说则是随机数据跑的飞快,替罪羊因为是暴力重构所以可以拿到树套树的外层来套个主席树。。。

而splay就是玄学了。。

替罪羊:

//#include <bits/stdc++.h>
#include <iostream>
#include <cstring>
#include <stdio.h>
#include <vector>
using namespace std;
const double A = 0.755;
#define MAXN 200005
int len;
 
 
struct node{
    node *ch[2];
    int v,s,ex,cover;
    
    void Maintain(){
        s = ch[0] -> s + ch[1]->s + ex;
        cover = ch[0] -> cover + ch[1] ->cover +1;
    }
 
    inline bool bad(){
        return ch[0]->cover >= cover * A +5 || ch[1]->cover >= cover * A +5;
    }
 
    void* operator new (size_t);
 
    void operator delete (void *p);
 
    node(){
        s = cover = ex = 0;
        ch[0]=ch[1]=NULL;
    }
 
    node(int x);
}*null=new node(),*root,*lst[MAXN],*S,*T;
vector<node*>Stack;
 
 
void* node :: operator new (size_t size){
    node *p;
    if(!Stack.empty()){
        p=Stack.back();
        Stack.pop_back();
    }
    else{
        if(S==T){
            S=new node[1<<15];
            T=S+(1<<15);
        }
        p=S++;
    }
    return p;
}
 
void node :: operator delete (void *p){
    Stack.push_back((node*)p);
}
 
node :: node(int x){
    v=x;s=1;cover=1;ex=1;
    ch[0]=ch[1]=null;
}
 
void travel(node *p){
    if(p == null)return;
    travel(p->ch[0]);
    if(p->ex)lst[++len]=p;
    else delete p;
    travel(p->ch[1]);
    
}
 
node *divide(int l,int r){
    if(l>r)return null;
    int m = l+r>>1;
    lst[m]->ch[0]=divide(l,m-1);
    lst[m]->ch[1]=divide(m+1,r);
    lst[m]->Maintain();
    return lst[m];
}
 
inline void rebuild(node *&p){
    len = 0;
    travel(p);
    p = divide(1,len);
}
 
node **insert(node *&o,int x){
    if(o == null){
        o = new node(x);
        return &null;
    }
    node **ret = insert(o->ch[o->v<=x],x);
    o->Maintain();
    if(o->bad())ret = &o;
    return ret;
}
 
void erase(node *p,int k){
    if(p->ex && k == p->ch[0]->s+1){
        p->ex=0;
        p->Maintain();
        return;
    }
    if(k <= p->ch[0]->s) erase (p->ch[0],k);
    else erase(p->ch[1],k - p->ch[0]->s - p->ex);
    p->Maintain();
}
 
inline int Rank(int x){
    node *o = root;
    int ans = 0;
    while(o!=null){
        if(o->v >=x ) o = o->ch[0];
        else ans+=o->ch[0]->s+o->ex,o=o->ch[1];
    }
    return ans+1;
}
 
node* kth(int k){
    node *o = root;
    while(o!=null){
        if(o->ex && k == o->ch[0]->s+1)return o;
        else if(o->ch[0]->s>=k)o=o->ch[0];
        else k-=o->ch[0]->s+o->ex,o=o->ch[1];
    }
    return null;
}
 
void Erase(int x){
    erase(root,Rank(x));
    if(root->s < root->cover *A)rebuild(root);
}
 
void insert(int x){
    node **p=insert(root,x);
    if(*p!=null)rebuild(*p);
}
 
int main(){
    freopen("phs.in","r",stdin);
    freopen("phs.out","w",stdout);
    root = null;
    int q,opt,x;
    scanf("%d",&q);
    while(q--){
        scanf("%d%d", &opt, &x);
        switch (opt){
            case 1:insert(x);break;
            case 2:Erase(x);break;
            case 3:printf("%d\n", Rank(x));break;
            case 4:printf("%d\n", kth(x)->v);break;
            case 5:printf("%d\n", kth(Rank(x) - 1)->v);break;
            case 6:printf("%d\n", kth(Rank(x + 1))->v);break;
        }
    }
}
splay:

#include <cstdio>
#include <cstring>
#define inf 2e9
 
 
struct node{
	int v,s;
	node *ch[2],*f;
	node(){
		s=0;
		v=0;
		ch[0]=ch[1]=NULL;
		f=NULL;
	}
	node(int x);
	void Maintain(){
		s=ch[0]->s+ch[1]->s+1;
	}
}*root,*null=new node();
 
node::node(int x){
	v=x;
	s=1;
	ch[0]=ch[1]=null;
	f=null;
}
 
inline int cmp(node *x){return x->f->ch[0]==x;}
 
inline void rotate(node *x,int d){
	node *y=x->ch[d^1];
	if(x->f!=null)x->f->ch[cmp(x)^1]=y;
	else root=y;
	y->f=x->f;
	x->ch[d^1]=y->ch[d];
	if(y->ch[d]!=null)y->ch[d]->f=x;
	y->ch[d]=x;
	x->f=y;
	x->Maintain();
	y->Maintain();
}
 
void splay(node *x,node *t=null){
	for(node *rt=x->f;rt!=t;rt=x->f){
		if(rt->f==t){
			rotate(rt,cmp(x));
			return;
		}
		if(cmp(x)==cmp(rt))rotate(rt->f,cmp(x));
		else rotate(rt,cmp(x));
		rotate(x->f,cmp(x));
	}
}
 
int rank(int x){
	int ans=0;
	node *rt=root;
	while(rt!=null){
		if(x>rt->v)ans+=rt->ch[0]->s+1,rt=rt->ch[1];
		else rt=rt->ch[0];
	}
	return ans;
}
 
node* kth(int k){
	node *rt=root;
	while(rt!=null){
		if(rt->ch[0]->s+1==k)return rt;
		if(rt->ch[0]->s+1>k)rt=rt->ch[0];
		else k-=rt->ch[0]->s+1,rt=rt->ch[1];
	}
	return null;
}
 
void insert(int x){
	int Rank=rank(x);
	splay(kth(Rank));splay(kth(Rank+1),root);
	node *y=new node(x);
	root->ch[1]->ch[0]=y;
	y->f=root->ch[1];
	root->ch[1]->Maintain();
	root->Maintain();
}
 
void del(int x){
	int Rank=rank(x)+1;
	splay(kth(Rank-1));splay(kth(Rank+1),root);
	root->ch[1]->ch[0]=null;
	root->ch[1]->Maintain();
	root->Maintain();
}
 
int main(){
#define LOCAL
#ifdef LOCAL 
	freopen("phs.in","r",stdin);
	freopen("phs.out","w",stdout);
#endif
	root=new node(-inf);
	root->ch[1]=new node(inf);
	root->ch[1]->f=root;
	int n;
	scanf("%d",&n);
	while(n--){
		int op,x;
		scanf("%d%d",&op,&x);
		switch(op){
			case 1:insert(x);break;
			case 2:del(x);break;
			case 3:printf("%d\n",rank(x));break;
			case 4:printf("%d\n",kth(x+1)->v);break;
			case 5:printf("%d\n",kth(rank(x))->v);break;
			case 6:printf("%d\n",kth(rank(x+1)+1)->v);
		}
	}
}

wq大佬是称霸一时的丛林之王,话说wq背着一包树苗去NOIP高高兴兴的去植树,却发现人家不缺绿化。。

posted @ 2017-07-12 21:24  cooook  阅读(142)  评论(0编辑  收藏  举报