终于想起来我今天干嘛了。
没错,我要写替罪羊树啊。
然后发现已经到晚上了 〒▽〒 简直不像话
数落一下发现今天学到的都好奇怪(。・・)ノ我的天我今天到底在干嘛。
于是还是水(抄)了一发替罪羊树。
写完之后感觉我整个人都要拍扁重建了。
不造为什么我的替罪羊树跑得木有SBT快,不科学啊。
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
using namespace std;
template<class T>void read(T &x){
static char c;
static bool f;
for(f=0;c=getchar(),!isdigit(c);)if(c=='-')f=1;
for(x=0;isdigit(c);c=getchar())x=x*10+c-'0';
if(f)x=-x;
}
const int N=200000+10;
const double alpha=0.75;
struct Node{
Node *ch[2];
int sz,v,cnt;
bool ex;
bool scapegoat(){
return ch[0]->cnt>alpha*cnt+5||ch[1]->cnt>alpha*cnt+5;
}
void pushup(){
sz=ch[0]->sz+ch[1]->sz+ex;
cnt=ch[0]->cnt+ch[1]->cnt+1;
}
};
struct ScapegoatTree{
Node pool[N];
Node *tail,*root,*null;
Node *bc[N];
Node *v[N];
int bc_top,top;
void init(){
tail=pool;
null=tail++;
null->ch[0]=null->ch[1]=null;
null->sz=null->v=null->cnt=0;
root=null;
bc_top=0;
}
Node *newnode(int v){
Node *p;
if(bc_top)p=bc[--bc_top];
else p=++tail;
p->ch[0]=p->ch[1]=null;
p->v=v;
p->sz=1;
p->cnt=1;
p->ex=true;
return p;
}
void travel(Node *p){
if(p==null)return;
travel(p->ch[0]);
if(p->ex)v[++top]=p;
else bc[bc_top++]=p;
travel(p->ch[1]);
}
Node *divide(int l,int r){
if(l>r)return null;
int mid=l+r>>1;
Node *p=v[mid];
p->ch[0]=divide(l,mid-1);
p->ch[1]=divide(mid+1,r);
p->pushup();
return p;
}
void rebuild(Node *&p){
top=0;
travel(p);
p=divide(1,top);
}
Node **insert(Node *&p,int val){
if(p==null){
p=newnode(val);
return &null;
}else{
p->sz++;
p->cnt++;
int k=val>=p->v;
Node **res=insert(p->ch[k],val);
if(p->scapegoat())res=&p;
return res;
}
}
void insert(int val){
Node **p=insert(root,val);
if(*p!=null)rebuild(*p);
}
void erase(Node *p,int id){
p->sz--;
if(p->ex&&id==p->ch[0]->sz+1)
p->ex=0;
else{
if(id<=p->ch[0]->sz+p->ex)
erase(p->ch[0],id);
else erase(p->ch[1],id-p->ch[0]->sz-p->ex);
}
}
int rank(int val){
Node *now=root;
int ans=1;
while(now!=null){
if(now->v>=val)now=now->ch[0];
else{
ans+=now->ch[0]->sz+now->ex;
now=now->ch[1];
}
}
return ans;
}
int kth(int k){
Node *now=root;
while(now!=null){
if(now->ex&&k==now->ch[0]->sz+1)
return now->v;
else if(k<=now->ch[0]->sz)
now=now->ch[0];
else{
k-=now->ch[0]->sz+now->ex;
now=now->ch[1];
}
}
}
void erase(int val){
erase(root,rank(val));
if(root->sz<alpha*root->cnt)rebuild(root);
}
int pre(int x){
return kth(rank(x)-1);
}
int suc(int x){
return kth(rank(x+1));
}
}sc;
int main(){
int n;read(n);
int opt,x;
sc.init();
while(n--){
read(opt);read(x);
switch(opt){
case 1:sc.insert(x);break;
case 2:sc.erase(x);break;
case 3:printf("%d\n",sc.rank(x));break;
case 4:printf("%d\n",sc.kth(x));break;
case 5:printf("%d\n",sc.pre(x));break;
case 6:printf("%d\n",sc.suc(x));break;
}
}
return 0;
}