郁闷的出纳员
约等于平衡树模板题。不知道为什么平衡树似乎总是和我有仇,怎么写怎么错。仅以此篇博客纪念我与平衡树之间的斗争的阶段性胜利。
这道题相当于是要求支持三个操作,插入,查找排名为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;
}
一如既往,万事胜意
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· 写一个简单的SQL生成工具
· AI 智能体引爆开源社区「GitHub 热点速览」
· C#/.NET/.NET Core技术前沿周刊 | 第 29 期(2025年3.1-3.9)