【模板】帶旋Treap(指標實現)
阿新 • • 發佈:2018-12-13
解析:
聯賽結束後統一更模板題題解。 陣列實現看這裡
程式碼:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define re register
#define gc getchar
#define pc putchar
#define cs const
inline
int getint(){
re int num;
re char c;
while(!isdigit(c=gc()));num=c^48;
while(isdigit(c=gc()))num=(num<< 1)+(num<<3)+(c^48);
return num;
}
inline
void outint(int a){
static char ch[13];
if(a==0)pc('0');
if(a<0)pc('-'),a=-a;
while(a)ch[++ch[0]]=a-a/10*10,a/=10;
while(ch[0])pc(ch[ch[0]--]^48);
}
cs int INF=0x3f3f3f3f;
typedef struct treap_node *point;
struct treap_node{
point lc,rc;
int val,pri,siz, cnt;
treap_node(){
lc=rc=NULL;
val=pri=siz=cnt=0;
}
void init(int _val){
lc=rc=NULL;
val=_val;
pri=rand();
siz=cnt=1;
}
void update(){
siz=(lc==NULL?0:lc->siz)+(rc==NULL?0:rc->siz)+cnt;
}
};
struct TREAP{
point root;
void Zig(point &k){
point y=k->lc;
k->lc= y->rc;
y->rc=k;
y->siz=k->siz;
k->update();
k=y;
}
void Zag(point &k){
point y=k->rc;
k->rc=y->lc;
y->lc=k;
y->siz=k->siz;
k->update();
k=y;
}
void insert(point &k,cs int &key){
if(k==NULL){
k=(point)malloc(sizeof(treap_node));
k->init(key);
return ;
}
++k->siz;
if(k->val==key)return (void)(++k->cnt);
if(key>k->val){
insert(k->rc,key);
if(k->rc->pri>k->pri)Zag(k);
}
else {
insert(k->lc,key);
if(k->lc->pri>k->pri)Zig(k);
}
}
void Insert(cs int &key){insert(root,key);}
void del(point &k,cs int &key){
if(k==NULL)return ;
if(k->val==key){
if(k->cnt>1)--k->cnt,--k->siz;
else if(!k->lc)/*free(k),*/k=k->rc;//不節約空間可以這樣寫,
else if(!k->rc)/*free(k),*/k=k->lc;//如果要節約空間請先用tmp保留要指向的兒子,再用free函式
else if(k->lc->pri>k->rc->pri)Zig(k),del(k,key);
else Zag(k),del(k,key);
return ;
}
--k->siz;
if(key>k->val)del(k->rc,key);
else del(k->lc,key);
}
void Delete(cs int &key){del(root,key);}
int queryrank(cs int &key){
point k=root;
int ans=0;
while(k){
if(k->val==key)return ans+(k->lc?k->lc->siz:0);
if(k->val>key)k=k->lc;
else ans+=(k->lc?k->lc->siz:0)+k->cnt,k=k->rc;
}
return ans;
}
int querykth(int Rank){
point k=root;
while(k){
int res=k->lc?k->lc->siz:0;
if(res<Rank&&res+k->cnt>=Rank)return k->val;
if(res>=Rank)k=k->lc;
else Rank-=res+k->cnt,k=k->rc;
}
return 0;
}
int querypre(cs int &key){
point k=root;
int ans=-INF;
while(k){
if(k->val>=key)k=k->lc;
else ans=k->val,k=k->rc;
}
return ans==-INF?-1:ans;
}
int querysuf(cs int &key){
point k=root;
int ans=INF;
while(k){
if(k->val<=key)k=k->rc;
else ans=k->val,k=k->lc;
}
return ans==INF?-1:ans;
}
}Treap;
int n;
signed main(){
n=getint();
while(n--){
int op=getint(),x=getint();
int ans;
switch(op){
case 0:Treap.Insert(x);break;
case 1:Treap.Delete(x);break;
case 2:outint(Treap.querykth(x)),pc('\n');break;
case 3:outint(Treap.queryrank(x)),pc('\n');break;
case 4:outint(Treap.querypre(x)),pc('\n');break;
case 5:outint(Treap.querysuf(x)),pc('\n');break;
}
}
return 0;
}