题意:
平衡树的一系列操作。
题解:无旋Treap/替罪羊
作为一个用Splay水过无数道题的人,第一次写无旋Treap表示很慌。。
#include<bits/stdc++.h>
using namespace std;
typedef unsigned int uint;
struct IO{
streambuf *ib,*ob;
inline void init(){
ios::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
ib=cin.rdbuf();ob=cout.rdbuf();
}
inline int read(){
char ch=ib->sbumpc();int i=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=ib->sbumpc();}
while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=ib->sbumpc();}
return i*f;
}
inline void W(long long x){
static int buf[50];
if(!x){ob->sputc('0');return;}
if(x<0){ob->sputc('-');x=-x;}
while(x)buf[++buf[0]]=x%10,x/=10;
while(buf[0])ob->sputc(buf[buf[0]--]+'0');
}
inline uint unit(){
static uint state0=23333;
state0^=state0<<13;
state0^=state0<<17;
state0^=state0>>5;
return state0;
}
}io;
const int Maxn=1e5+50;
int n;
struct node{
node *lc,*rc;
int sze,val;
uint pri;
node();
inline void upt(){
sze=lc->sze+rc->sze+1;
}
}Pool[Maxn],*pool=Pool,*null=Pool;
node::node():lc(null),rc(null){}
typedef pair<node*,node*> pii;
struct RecyclePool{
node *que[Maxn];
int tail;
inline node* newnode(int val){
static node* tmp;
tmp=(tail?que[tail--]:++pool);
tmp->lc=tmp->rc=null;
tmp->sze=1;tmp->val=val;tmp->pri=io.unit();
return tmp;
}
}recyclepool;
struct Treap{
node *rt;
Treap():rt(null){}
inline int getrank(int val){
node *tmp=rt;int k=0;
if(tmp==null)return 0;
while(tmp!=null){
if(tmp->val<val){k+=(tmp->lc->sze+1);tmp=tmp->rc;}
else tmp=tmp->lc;
}
return k;
}
inline node* merge(node *x,node *y){
if(x==null)return y;if(y==null)return x;
if(x->pri<y->pri){
x->rc=merge(x->rc,y);x->upt();
return x;
}
else{
y->lc=merge(x,y->lc);y->upt();
return y;
}
}
inline pii split(node *now,int k){
if(now==null)return pii(null,null);
if((now->lc->sze+1<=k)){
pii tr=split(now->rc,k-now->lc->sze-1);
now->rc=tr.first;now->upt();
return pii(now,tr.second);
}
else{
pii tr=split(now->lc,k);
now->lc=tr.second;now->upt();
return pii(tr.first,now);
}
}
inline void insert(int val){
int k=getrank(val);
pii tr=split(rt,k);
node *tmp=recyclepool.newnode(val);
rt=merge(merge(tr.first,tmp),tr.second);
}
inline void remove(int val){
int k=getrank(val);
pii tr1=split(rt,k);
pii tr2=split(tr1.second,1);
rt=merge(tr1.first,tr2.second);
recyclepool.que[++recyclepool.tail]=tr2.first;
}
inline int getkth(node *now,int k){
if(now->lc->sze+1<k)return getkth(now->rc,k-now->lc->sze-1);
else if(now->lc->sze+1==k)return now->val;
return getkth(now->lc,k);
}
}treap;
int main(){
io.init();n=io.read();
for(int i=1;i<=n;i++){
int op=io.read();
if(op==1){treap.insert(io.read());}
else if(op==2){treap.remove(io.read());}
else if(op==3){io.W(treap.getrank(io.read())+1);io.ob->sputc('\n');}
else if(op==4){io.W(treap.getkth(treap.rt,io.read()));io.ob->sputc('\n');}
else if(op==5){io.W(treap.getkth(treap.rt,treap.getrank(io.read())));io.ob->sputc('\n');}
else {io.W(treap.getkth(treap.rt,treap.getrank(io.read()+1)+1));io.ob->sputc('\n');}
}
}
写完替罪羊发现不重构可以过。。于是正解原来是二叉搜索树???
#include<bits/stdc++.h>
using namespace std;
const int alpha=75;
struct IO{
streambuf *ib,*ob;
inline void init(){
ios::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
ib=cin.rdbuf();ob=cout.rdbuf();
}
inline int read(){
char ch=ib->sbumpc();int i=0,f=1;
while(!isdigit(ch)){if(ch=='-')f=-1;ch=ib->sbumpc();}
while(isdigit(ch)){i=(i<<1)+(i<<3)+ch-'0';ch=ib->sbumpc();}
return i*f;
}
inline void W(int x){
static int buf[50];
if(!x){ob->sputc('0');ob->sputc('\n');return;}
if(x<0){ob->sputc('-');x=-x;}
while(x){buf[++buf[0]]=x%10;x/=10;}
while(buf[0]){ob->sputc(buf[buf[0]--]+'0');}
ob->sputc('\n');
}
}io;
const int Maxn=1e5+50;
int n;
struct node{
node *lc,*rc;
node():lc(NULL),rc(NULL){}
int sze,val,cnt;
inline void upt(){
sze=lc->sze+rc->sze+cnt;
}
}Pool[Maxn],*pool=Pool,*null=Pool,*rt=null;
inline node* newnode(int val){
++pool;
pool->lc=pool->rc=null;
pool->sze=pool->cnt=1;pool->val=val;
return pool;
}
inline void insert_val(node*& now,int val,node**&p){
if(now==null){now=newnode(val);return;}
if(val<now->val)insert_val(now->lc,val,p);
else if(val>now->val)insert_val(now->rc,val,p);
else now->cnt++;
now->upt();
if(100*now->lc->sze>=now->sze*alpha||100*now->rc->sze>=now->sze*alpha)p=&now;
}
inline void erase_val(node*& now,int val,node **&p){
if(now->val==val)now->cnt--;
else if(now->val<val)erase_val(now->rc,val,p);
else erase_val(now->lc,val,p);
now->upt();
if(100*now->lc->sze>=now->sze*alpha||100*now->rc->sze>=now->sze*alpha)p=&now;
}
node* que[Maxn];int tail=0;
inline void traval(node *p){
if(p->lc->sze)traval(p->lc);
if(p->cnt)que[++tail]=p;
if(p->rc->sze)traval(p->rc);
}
inline node* build(int l,int r){
static int cnt;
if(r<l)return null;
if(l==r){
que[l]->lc=que[l]->rc=null;
que[l]->sze=que[l]->cnt;
return que[l];
}
int mid=(l+r)>>1;
node* tmp=que[mid];
tmp->lc=build(l,mid-1);
tmp->rc=build(mid+1,r);
tmp->upt();
return tmp;
}
inline void rebuild(node *&p){
tail=0;traval(p);
int l=1,r=tail;
p=build(l,r);
}
inline void insert(node*& now,int val){
node **p=&null;
insert_val(now,val,p);
if(*p!=null)rebuild(*p);
}
inline void del(node*& now,int val){
node **p=&null;
erase_val(now,val,p);
if(*p!=null)rebuild(*p);
}
inline int getrank(int val){
int k=0;node *tmp=rt;
while(tmp!=null){
if(tmp->val<val)k+=tmp->lc->sze+tmp->cnt,tmp=tmp->rc;
else tmp=tmp->lc;
}
return k+1;
}
inline int getkth(node *now,int kth){
if(now->lc->sze>=kth)return getkth(now->lc,kth);
else if(now->lc->sze+now->cnt>=kth)return now->val;
else return getkth(now->rc,kth-now->lc->sze-now->cnt);
}
inline int getpre(int val){
node *tmp=rt;int last;
while(tmp!=null){
if(tmp->val>=val)tmp=tmp->lc;
else last=tmp->val,tmp=tmp->rc;
}
return last;
}
inline int getsuf(int val){
node *tmp=rt;int last;
while(tmp!=null){
if(tmp->val<=val)tmp=tmp->rc;
else last=tmp->val,tmp=tmp->lc;
}
return last;
}
int main(){
io.init();n=io.read();
for(int i=1;i<=n;i++){
int op=io.read();
if(op==1){
insert(rt,io.read());
}
else if(op==2){
del(rt,io.read());
}
else if(op==3){
io.W(getrank(io.read()));
}
else if(op==4){
io.W(getkth(rt,io.read()));
}
else if(op==5){
io.W(getkth(rt,getrank(io.read())-1));
}
else io.W(getkth(rt,getrank(io.read()+1)));
}
}