博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
洛谷P1801 黑匣子
阅读量:7225 次
发布时间:2019-06-29

本文共 3153 字,大约阅读时间需要 10 分钟。

题目描述

Black Box是一种原始的数据库。它可以储存一个整数数组,还有一个特别的变量i。最开始的时候Black Box是空的.而i等于0。这个Black Box要处理一串命令。

命令只有两种:
ADD(x):把x元素放进BlackBox;
GET:i加1,然后输出BlackBox中第i小的数。
记住:第i小的数,就是Black Box里的数的按从小到大的顺序排序后的第i个元素。例如:
我们来演示一下一个有11个命令的命令串。(如下图所示)
(图挂了)
现在要求找出对于给定的命令串的最好的处理方法。ADD和GET命令分别最多200000个。现在用两个整数数组来表示命令串:
1. A(1)A(2),…A(M):一串将要被放进Black Box的元素。每个数都是绝对值不超过2000000000的整数,M200000。例如上面的例子就是A=(3,1,4,2,8,1000,2)
2. u(1),u(2),u(N):表示第u(j)个元素被放进了Black Box里后就出现一个GET命令。例如上面的例子中u=(1,2,6,6)。输入数据不用判错。

输入输出格式

输入格式:

第一行,两个整数,MN

第二行,M个整数,表示A(1)...A(M)
第三行,N个整数,表示u(l)...u(N)

输出格式:

输出Black Box根据命令串所得出的输出串,一个数字一行。

输入输出样例

输入样例#1:

7 4

3 1 -4 2 8 -1000 2
1 2 6 6

输出样例#1:

3

3
1
2

说明

对于30%的数据,M10000

对于50%的数据,M100000
对于100%的数据,M200000

思路

有两种方法:

第一种:强行splay大法,直接按照题目意思在splay上操作。(splay可以换成其他的BST)
第二种:标准方法(堆),既然询问的k是递增的,那么可以把前k1小的数丢到一个大根堆中,剩下的数丢到一个小根堆中,操作步骤:
1. 每加入一个数,先丢到大根堆中,再将大根堆中最大的数取出来丢到小根堆中;
2. 询问第k大的数,只需要输出小根堆中的数,然后丢到大根堆中。
3. 正确性?加入的时候,如果加入的数是加入后的数列中前k小的,那么大根堆中就是前k小的所有数,应当去除第k大的数;如果不是前k小的,那么大根堆中就是前k1小的数加上加入的数,加入的数一定是大根堆中最大的,去除堆顶放入小根堆。
4. 询问的时候,小根堆中最小的数一定是第k大的,而将其取出后由于k需要加1为下一次询问做准备,那么应当将第k大转移到大根堆中。

代码(splay版)

#include 
const int maxn=200000;struct splay_tree{ int fa[maxn+10],son[2][maxn+10],val[maxn+10],size[maxn+10],tot,root; int t(int x) { return son[1][fa[x]]==x; } int updata(int x) { size[x]=1; if(son[0][x]) { size[x]+=size[son[0][x]]; } if(son[1][x]) { size[x]+=size[son[1][x]]; } return 0; } int rotate(int x) { int k=t(x),f=fa[x]; fa[x]=fa[f]; if(fa[f]) { son[t(f)][fa[f]]=x; } son[k][f]=son[!k][x]; if(son[!k][x]) { fa[son[!k][x]]=f; } son[!k][x]=f; fa[f]=x; updata(f); updata(x); return 0; } int splay(int x,int c) { while(fa[x]!=c) { int f=fa[x]; if(fa[f]==c) { rotate(x); } else if(t(x)==t(f)) { rotate(f); rotate(x); } else { rotate(x); rotate(x); } } if(!c) { root=x; } return 0; } int newnode(int x) { ++tot; val[tot]=x; size[tot]=1; return 0; } int ins(int x) { newnode(x); if(!root) { root=tot; fa[tot]=son[0][tot]=son[1][tot]=0; return 0; } int now=root; while(now) { int p=val[now]

代码(堆版)

#include 
#include
//pbds神教,速度比STL堆快,支持两堆的合并const int maxn=200000;__gnu_pbds::priority_queue
> box;//建立一个小根堆__gnu_pbds::priority_queue
w;//建立一个大根堆long long sw,m,n,now;long long a[maxn+10],u[maxn+10];int main(){ now=1; scanf("%lld%lld",&m,&n); for(int i=1; i<=m; i++) { scanf("%lld",&a[i]); } for(int i=1; i<=n; i++) { scanf("%lld",&u[i]); } for(int i=1; i<=m; i++) { w.push(a[i]); box.push(w.top()); w.pop(); while(i==u[now]) { printf("%lld\n",box.top()); w.push(box.top()); box.pop(); now++; } } return 0;}

转载于:https://www.cnblogs.com/Canopus-wym/p/10376260.html

你可能感兴趣的文章
七牛实时音视频云视频连线demo(web部分)
查看>>
Netty源码分析(六):SelectedSelectionKeySetSelector
查看>>
forEach,for...of,map与asycn/await
查看>>
springboot 2 Hikari 多数据源配置问题(dataSourceClassName or jdbcUrl is required)
查看>>
Golang数据库编程之GORM模型定义与数据库迁移
查看>>
Oracle redo解析之-4、rowid的计算
查看>>
Easy Scheduler 1.0.3 发布,分布式工作流任务调度系统
查看>>
java 颠倒整数
查看>>
Python入门教程100天:Day05-练习总结
查看>>
环境搭建,8种基本类型,Static,package和import,log4j
查看>>
即将到来的 Debian 10 Buster 发布版的新特点
查看>>
iOS 头部视图下拉变大
查看>>
Disruptor并发框架
查看>>
react-hooks 实现简单的评论list
查看>>
【多图警告】学会JavaScript测试你就是同行中最亮的仔(妹)
查看>>
19-04-25
查看>>
一个JAVA程序员成长之路分享
查看>>
30K iOS程序员的简述:如何快速进阶成为高级开发人员
查看>>
Go 夜读 - 每周四晚上 Go 源码阅读技术分享
查看>>
tranform知多少
查看>>