经典裸题。对于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高高兴兴的去植树,却发现人家不缺绿化。。