#include<vector>
using namespace std;
namespace Scapegoat_Tree{
#define MAXN (100000 + 10)
const double alpha = 0.75;
struct Node{
Node * ch[2];
int key,size,cover;
bool exist;
void Pushup(void){
size=ch[0]->size+ch[1]->size+(int)exist;
cover=ch[0]->cover+ch[1]->cover+1;
}
bool isBad(void){
return ((ch[0]->cover>cover*alpha+5)||
(ch[1]->cover>cover*alpha+5));
}
};
struct STree{
protected:
Node mem_poor[MAXN];
Node *tail,*root,*null;
Node *bc[MAXN];
int bc_top;
Node *NewNode(int key){
Node *p=bc_top?bc[--bc_top]:tail++;
p->ch[0]=p->ch[1]=null;
p->size=p->cover=1;
p->key=key;
p->exist=true;
return p;
}
void Travel(Node *p,vector<Node *>v){
if(p==null)return;
Travel(p->ch[0],v);
if(p->exist)v.push_back(p);
else bc[bc_top++]=p;
Travel(p->ch[1],v);
p->Pushup();
return;
}
Node *Divide(vector<Node *>&v,int l,int r){
if(l>=r)return null;
int mid=(l+r)>>1;
Node *p=v[mid];
p->ch[0]=Divide(v,l,mid);
p->ch[1]=Divide(v,mid+1,r);
p->Pushup();
return p;
}
void Rebuild(Node *&p){
static vector<Node *>v;
v.clear();Travel(p,v);
p=Divide(v,0,v.size());
return;
}
Node ** Insert(Node *&p,int val){
if(p==null){
p=NewNode(val);
return &null;
}else{
p->size++;p->cover++;
Node ** res = Insert(p->ch[val>=p->key],val);
if(p->isBad())res=&p;
return res;
}
}
void Erase(Node *p,int id){
p->size--;
int offset=p->ch[0]->size+p->exist;
if(p->exist&&id==offset){
p->exist=false;
return;
}else{
if(id<=offset)Erase(p->ch[0],id);
else Erase(p->ch[1],id-offset);
}
}
public:
void Init(void){
tail=mem_poor;
null=tail++;
null->ch[0]=null->ch[1]=null;
null->size=null->cover=null->key=0;
null->exist=false;
root=null;bc_top=0;
return;
}
Stree(void){Init();}
void Insert(int val){
Node ** p=Insert(root,val);
if(*p!=null)Rebuild(*p);
}
int Rank(int val){
Node *now=root;
int ans=1;
while(now!=null){
if(now->key>=val)now=now->ch[0];
else{
ans+=now->ch[0]->size+now->exist;
now=now->ch[1];
}
}
return ans;
}
int Kth(int k){
Node * now=root;
while(now!=null){
if(now->ch[0]->size+1==k&&now->exist)return now->key;
else if(now->ch[0]->size>=k)now=now->ch[0];
else k-=now->ch[0]->size+now->exist,now=now->ch[1];
}
}
void Erase(int k) {
Erase(root, Rank(k));
if(root->size<alpha*root->cover)Rebuild(root);
}
void Erase_kth(int k) {
Erase(root, k);
if(root->size<alpha*root->cover)Rebuild(root);
}
};
#undef MAXN
}
/*
main() for luogu p3369 普通平衡树 :
int main(void) {
//freopen("in.txt", "r", stdin);
//freopen("out.txt", "w", stdout);
read(n);
while (n--) {
read(k), read(m);
switch (k) {
case 1: _t.Insert(m); break;
case 2: _t.Erase(m); break;
case 3: printf("%d\n", _t.Rank(m)); break;
case 4: printf("%d\n", _t.Kth(m)); break;
case 5: printf("%d\n", _t.Kth(_t.Rank(m) - 1)); break;
case 6: printf("%d\n", _t.Kth(_t.Rank(m + 1))); break;
}
}
return 0;
}
Outside of main:
void read(int &x);//快读,略
using namespace Scapegoat_Tree;
STree_t;
int n,k,m;
*/
https://zhuanlan.zhihu.com/p/21263304