郁闷的出纳员

link

约等于平衡树模板题。不知道为什么平衡树似乎总是和我有仇,怎么写怎么错。仅以此篇博客纪念我与平衡树之间的斗争的阶段性胜利。

这道题相当于是要求支持三个操作,插入,查找排名为k的数,删除小于某个值的所有元素。这些都是平衡树的基本操作,第三个只需插入一个那样的节点,把它旋转到根部,如何删除左子树即可。

以上操作似乎SPLAY或者无旋treap要好弄一些,但我还没写过……

#include<cstdio>
#include<ctime>
#include<cstdlib>
//#define zczc
const int N=300010;
inline void read(int &wh){
    wh=0;int f=1;char w=getchar();
    while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
    while(w<='9'&&w>='0'){wh=wh*10+w-'0';w=getchar();}
    wh*=f;return;
}

int m,n,add,in,root,ans;
char w;

#define lc t[wh].l
#define rc t[wh].r
struct node{
	int l,r,data,sum,num,p;
}t[N<<1];
int cnt;
inline int newone(int val){
	t[++cnt].data=val;t[cnt].num=t[cnt].sum=1;
	t[cnt].p=rand();return cnt;
}
inline void pushup(int wh){
	t[wh].sum=t[lc].sum+t[rc].sum+t[wh].num;
}
inline int zig(int wh){
	int a=wh,b=lc,c=t[lc].r;
	return t[a].l=c,pushup(a),t[b].r=a,pushup(b),b;
}
inline int zag(int wh){
	int a=wh,b=rc,c=t[rc].l;
	return t[a].r=c,pushup(a),t[b].l=a,pushup(b),b;
}
int insert(int wh,int val){
	if(!wh)return newone(val);
	if(t[wh].data==val)return t[wh].num++,t[wh].sum++,wh;
	if(val<t[wh].data)lc=insert(lc,val);
	else rc=insert(rc,val);
	if(t[lc].num&&t[lc].p<t[wh].p)wh=zig(wh);
	if(t[rc].num&&t[rc].p<t[wh].p)wh=zag(wh);
	return pushup(wh),wh;
}
int del(int wh,int val){
	if(t[wh].data==val){
		if(t[wh].num>1)return t[wh].num--,t[wh].sum--,wh;
		if(!lc&&!rc)return 0;
		wh=t[lc].p>t[rc].p?zig(wh):zag(wh);
	}
	if(val<t[wh].data)lc=del(lc,val);
	else rc=del(rc,val);return pushup(wh),wh;
}
int get(int wh,int rk){
	if(!wh)return -1-add;
	if(t[rc].sum<rk&&rk<=t[rc].sum+t[wh].num)return t[wh].data;
	if(rk<=t[rc].sum)return get(rc,rk);
	else return get(lc,rk-t[rc].sum-t[wh].num);
}
int move(int wh,int val){
	if(t[wh].data==val)return wh;
	if(val<t[wh].data)lc=move(lc,val),wh=zig(wh);
	else rc=move(rc,val),wh=zag(wh);return wh;
}
#undef lc
#undef rc

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	srand(time(0));
	read(m);read(n);
	while(m--){
		w=getchar();while(w<'A'||w>'Z')w=getchar();read(in);
		if(w=='I'){
			if(in<n)continue;in-=add;
			root=insert(root,in);
		}
		else if(w=='A')add+=in;
		else if(w=='S'){
			add-=in;int want=n-add;
			root=insert(root,want);
			root=move(root,want);
			ans+=t[t[root].l].sum;
			t[root].sum-=t[t[root].l].sum;t[root].l=0;
			root=del(root,want);
		}
		else printf("%d\n",get(root,in)+add);
	}
	printf("%d",ans);
	
	return 0;
}
posted @ 2022-02-10 16:47  Feyn618  阅读(21)  评论(0编辑  收藏  举报