#define N (100000+10)
const double alpha=0.75;
struct Node
{
Node *ch[2];
int key,size,cover;// size为有效节点的数量,cover为节点总数量
bool exist;// 是否存在(即是否被删除)
void push_up()
{
size=ch[0]->size+ch[1]->size+(int)exist;
cover=ch[0]->cover+ch[1]->cover+1;
}
bool isBad()
{
return ((ch[0]->cover>cover*alpha+5)||(ch[1]->cover>cover*alpha+5));
}
};
struct Scapegoat_Tree
{
Node mem_poor[N];//内存池,直接分配好避免动态分配内存占用时间
Node *tail,*root,*null;// 用null表示NULL的指针更方便,tail为内存分配指针,root为根
Node *bc[N];// 储存被删除的节点的内存地址,分配时可以再利用这些地址
int bc_top;
Node *New_Node(int key)
{
Node *p=bc_top?bc[--bc_top]:tail++;
p->ch[0]=p->ch[1]=null;
p->size=p->cover=1,p->exist=true;
p->key=key;
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);
}
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->push_up();// 自底向上维护,先维护子树
return p;
}
void Rebuild(Node *&p)
{
static vector <Node*>v;
v.clear();
Travel(p,v);
p=Divide(v,0,v.size());
}
Node **Insert(Node *&p,int val)
{
if (p==null)
{
p=New_Node(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);
}
}
void Init()
{
tail=mem_poor;
null=tail++;
null->ch[0]=null->ch[1]=null;
null->cover=null->size=null->key=0;
root=null;
bc_top=0;
}
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)
{ // 非递归求第K大
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);
}
}stree;
struct Node
{
int key,sz,cnt;
int ch[2],pnt;
Node(){}
Node(int x,int y,int z)
{
key=x,sz=y,cnt=z;
}
}a[N<<1];
int root,ncnt;
void rs(int x)
{
a[x].sz=a[a[x].ch[0]].sz+a[a[x].ch[1]].sz+a[x].cnt;
}
void rotate(int x,bool d)
{
int y=a[x].pnt;
a[y].ch[!d]=a[x].ch[d];
if (a[x].ch[d]!=0) a[a[x].ch[d]].pnt=y;
a[x].pnt=a[y].pnt;
if (a[y].pnt!=0)
{
if (y==a[a[y].pnt].ch[d]) a[a[y].pnt].ch[d]=x;
else a[a[y].pnt].ch[!d]=x;
}
a[x].ch[d]=y;
a[y].pnt=x;
rs(y);
rs(x);
}
void splay(int x,int target)
{
int y;
while (a[x].pnt!=target)
{
y=a[x].pnt;
if (x==a[y].ch[0])
{
if (a[y].pnt!=target&&y==a[a[y].pnt].ch[0])
rotate(y,true);
rotate(x,true);
}
else
{
if (a[y].pnt!=target&&y==a[a[y].pnt].ch[1])
rotate(y,false);
rotate(x,false);
}
}
if (target==0) root=x;
}
void Insert(int key,int now,int number)
{
if (root==0)
{
root=now?now:(++ncnt);
a[root].ch[0]=a[root].ch[1]=a[root].pnt=0;
a[root].key=key;
a[root].sz=a[root].cnt=number;
return;
}
int x=root,y;
while (1)
{
a[x].sz+=number;
if (key==a[x].key)
{
a[x].cnt+=number;
a[x].sz+=number;
rs(x);
y=x;
break;
}
else
if (key<a[x].key)
{
if (a[x].ch[0]!=0) x=a[x].ch[0];
else
{
a[x].ch[0]=now?now:(++ncnt);
y=a[x].ch[0];
a[y].key=key;
a[y].sz=a[y].cnt=number;
a[y].ch[0]=a[y].ch[1]=0;
a[y].pnt=x;
break;
}
}
else
{
if (a[x].ch[1]!=0) x=a[x].ch[1];
else
{
a[x].ch[1]=now?now:(++ncnt);
y=a[x].ch[1];
a[y].key=key;
a[y].sz=a[y].cnt=number;
a[y].ch[0]=a[y].ch[1]=0;
a[y].pnt=x;
break;
}
}
}
splay(y,0);
}
int searchmin(int x)
{
int y=a[x].pnt;
while (a[x].ch[0]!=0) x=a[x].ch[0];
splay(x,y);
return x;
}
int search(int key)
{
if (root==0) return 0;
int x=root,y=0;
while (1)
{
if (key==a[x].key) break;
else
if (key>a[x].key)
{
if (a[x].ch[1]!=0) x=a[x].ch[1];
else break;
}
else
{
if (a[x].ch[0]!=0) x=a[x].ch[0];
else break;
}
}
y=x;
splay(x,0);
return y;
}
int Erase(int key,int number)
{
if (root==0) return 0;
int x=search(key),y;
if (x==0) return 0;
if (a[x].cnt>number)
{
a[x].cnt-=number;
a[x].sz-=number;
rs(x);
return 0;
}
else
if (a[x].ch[0]==0&&a[x].ch[1]==0)
{
root=0;
return x;
}
else
if (a[x].ch[0]==0)
{
root=a[x].ch[1];
a[a[x].ch[1]].pnt=0;
return x;
}
else
if (a[x].ch[1]==0)
{
root=a[x].ch[0];
a[a[x].ch[0]].pnt=0;
return x;
}
y=searchmin(a[x].ch[1]);
a[y].pnt=0;
a[y].ch[0]=a[x].ch[0];
a[a[x].ch[0]].pnt=y;
rs(y);
root=y;
return x;
}
int qry_kth(int x,int y)
{
int now=root;
while (now)
{
if (a[a[now].ch[0]].sz>=x) now=a[now].ch[0];
else
{
if (a[a[now].ch[0]].sz+a[now].cnt<x)
{
x-=a[a[now].ch[0]].sz+a[now].cnt;
now=a[now].ch[1];
}
else break;
}
}
return a[now].key;
}