luogu3369 【模板】普通平衡樹(Treap/SBT)
阿新 • • 發佈:2017-12-04
oid sin markdown 隨機 節點 nod -m rotate 編號
treap做法,參考hzwer的博客
#include <iostream>
#include <cstdlib>
#include <cstdio>
using namespace std;
struct Node{
int val, l, r, sze, rnd, hav;
//val代表當前節點的值,l、r是左右孩子編號,sze是以當前節點為根的子樹的大小
//rnd是一個隨機出來的權值, hav是當前節點的值對應的數字有幾個
}nd[100005];
int n, opt, x, rot, ans, num;
void update(int k){
nd[k].sze = nd[nd[k].l].sze + nd[nd[k].r].sze + nd[k].hav;
}
void lRotate(int &k){
int t=nd[k].r; nd[k].r = nd[t].l; nd[t].l = k;
nd[t].sze = nd[k].sze; update(k); k = t;
}
void rRotate(int &k){
int t=nd[k].l; nd[k].l = nd[t].r; nd[t].r = k;
nd[t].sze = nd[k].sze; update(k); k = t;
}
void ins(int &k, int x){
if(!k){
k = ++num; nd[k].sze = nd[k].hav = 1 ;
nd[k].val = x; nd[k].rnd = rand();
//創建一個新節點
return ;
}
nd[k].sze++;
if(nd[k].val==x) nd[k].hav++;
else if(x>nd[k].val){
ins(nd[k].r, x);
if(nd[nd[k].r].rnd<nd[k].rnd) lRotate(k);
//不滿足堆的性質則旋轉
}
else{
ins(nd[k].l, x);
if (nd[nd[k].l].rnd<nd[k].rnd) rRotate(k);
//不滿足堆的性質則旋轉
}
}
void del(int &k, int x){
if(!k) return ;
if(nd[k].val==x){
if(nd[k].hav>1){
nd[k].hav--; nd[k].sze--;
//要是有不止一個的話減一就好了
return ;
}
if(nd[k].l*nd[k].r==0) k = nd[k].l + nd[k].r;
//如果左右子樹有一個為空,則把k置為不為空的那顆子樹
//如果均為空,那麽k也變成了空
else if(nd[nd[k].l].rnd<nd[nd[k].r].rnd)
rRotate(k), del(k, x);
else lRotate(k), del(k, x);
}
else if(x>nd[k].val) nd[k].sze--, del(nd[k].r, x);
else nd[k].sze--, del(nd[k].l, x);
}
int queryRank(int k, int x){
if(!k) return 0;
if(nd[k].val==x) return nd[nd[k].l].sze+1;
else if(nd[k].val<x) return nd[nd[k].l].sze+nd[k].hav+queryRank(nd[k].r, x);
else return queryRank(nd[k].l, x);
}
int queryNum(int k, int x){
if(!k) return 0;
if(x<=nd[nd[k].l].sze) return queryNum(nd[k].l, x);
else if(x>nd[nd[k].l].sze+nd[k].hav) return queryNum(nd[k].r, x-nd[nd[k].l].sze-nd[k].hav);
else return nd[k].val;
}
void queryPre(int k, int x){
if(!k) return ;
if(nd[k].val<x) ans = k, queryPre(nd[k].r, x);
else queryPre(nd[k].l, x);
}
void queryNxt(int k, int x){
if(!k) return ;
if(nd[k].val>x) ans = k, queryNxt(nd[k].l, x);
else queryNxt(nd[k].r, x);
}
int main(){
cin>>n;
while(n--){
scanf("%d %d", &opt, &x);
if(opt==1) ins(rot, x);
if(opt==2) del(rot, x);
if(opt==3) printf("%d\n", queryRank(rot, x));
if(opt==4) printf("%d\n", queryNum(rot, x));
if(opt==5) queryPre(rot, x), printf("%d\n", nd[ans].val);
if(opt==6) queryNxt(rot, x), printf("%d\n", nd[ans].val);
}
return 0;
}
luogu3369 【模板】普通平衡樹(Treap/SBT)