【bzoj3224】【Tyvj 1728】 普通平衡树 树状数组
您需要写一种数据结构(可参考题目标题),来维护一些数,其中需要提供以下操作:
1. 插入x数
2. 删除x数(若有多个相同的数,因只删除一个)
3. 查询x数的排名(若有多个相同的数,因输出最小的排名)
4. 查询排名为x的数
5. 求x的前驱(前驱定义为小于x,且最大的数)
6. 求x的后继(后继定义为大于x,且最小的数)
数据范围:操作数≤105,x≤109。
这一题用平衡树做的方法是显然的,然而平衡树太长太慢,我们考虑写一个优美一点的算法。
首先先离散化所有读入的数(别离散化操作4!!!!)
然后,插入和删除操作显然(直接在离散化后的x处,赋值+1或者-1即可)
查询某个数的排名也是显然的。
考虑查询排名为x如何高速完成,此处不妨设x为正整数。
我们求一个最小的p,使得2p≥cnt,其中cnt为树状数组的长度。
设当前访问到的点为id(初始为0)
我们每次查询a[id+2p]上的值是否小于x,如果是x,那么id+=2p,然后x−=a[id]。
然后p--即可。
最后输出id+1即是第k大的数。
求前驱和后继:先求出给出的数是第几大的,然后+1或−1即可。
代码奇短
1 #include<bits/stdc++.h> 2 #define M 200000 3 #define lowbit(x) ((x)&(-x)) 4 using namespace std; 5 int a[M]={0},c[M]={0},n,cnt=0,m; 6 int op[M]={0},b[M]={0}; 7 void add(int x,int k){for(;x<=n;x+=lowbit(x)) a[x]+=k;} 8 int sum(int x){int k=0;for(;x;x-=lowbit(x)) k+=a[x]; return k;} 9 int getkth(int k){ 10 int id=0; 11 for(int i=n;i;i>>=1){ 12 if(k>a[id+i]) 13 k-=a[id+i],id+=i; 14 } 15 return id+1; 16 } 17 int main(){ 18 scanf("%d",&m); 19 for(int i=1;i<=m;i++){ 20 scanf("%d%d",op+i,b+i); 21 if(op[i]!=4) c[++cnt]=b[i]; 22 } 23 sort(c+1,c+cnt+1); 24 for(int i=1;i<=m;i++) 25 if(op[i]!=4) b[i]=lower_bound(c+1,c+cnt+1,b[i])-c; 26 for(n=1;n<=cnt;n<<=1); 27 for(int i=1;i<=m;i++){ 28 if(op[i]==1) add(b[i],1); 29 if(op[i]==2) add(b[i],-1); 30 if(op[i]==3) printf("%d\n",sum(b[i]-1)+1); 31 if(op[i]==4) printf("%d\n",c[getkth(b[i])]); 32 if(op[i]==5) printf("%d\n",c[getkth(sum(b[i]-1))]); 33 if(op[i]==6) printf("%d\n",c[getkth(sum(b[i])+1)]); 34 } 35 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· 零经验选手,Compose 一天开发一款小游戏!
· 一起来玩mcp_server_sqlite,让AI帮你做增删改查!!