[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高高兴兴的去植树,却发现人家不缺绿化。。