洛谷 [P1801] 黑匣子
这道题是一道splay裸题,然而身为蒟蒻的我并不会,所以这道题我维护的是一个大根堆与一个小根堆结合起来的类似沙漏的结构。
本题难点在于询问的不是最大最小值,而是第K小值,所以我们想到了维护这样两个堆,上面是一个大小限定为K-1的大根堆,下面是一个小根堆,每次插入/查询操作时,保持前K-1大的始终在大根堆内。
插入/查询函数:
int heap[200005][3],hsize[3];
int m,n,num[200005],temp;
void put(int x,int i){
heap[++hsize[i]][i]=x;
int son=hsize[i],pa=son>>1;
while(pa>=1){
if(i==1){
if(heap[pa][i]>heap[son][i]){
int t=heap[pa][i];heap[pa][i]=heap[son][i];heap[son][i]=t;
son=pa;
pa>>=1;
}else break;
}else {
if(heap[pa][i]<heap[son][i]){
int t=heap[pa][i];heap[pa][i]=heap[son][i];heap[son][i]=t;
son=pa;
pa>>=1;
}else break;
}
}
}
int get(int i){
int rv=heap[1][i];
heap[1][i]=heap[hsize[i]--][i];
int pa=1,son;
while(pa<=(hsize[i]>>1)){
if(i==1) son=heap[pa<<1][i]<heap[pa<<1|1][i]?pa<<1:pa<<1|1;
else son=heap[pa<<1][i]>heap[pa<<1|1][i]?pa<<1:pa<<1|1;
if(i==1){
if(heap[pa][i]>heap[son][i]){
int t=heap[pa][i];heap[pa][i]=heap[son][i];heap[son][i]=t;
pa=son;
}else break;
}else {
if(heap[pa][i]<heap[son][i]){
int t=heap[pa][i];heap[pa][i]=heap[son][i];heap[son][i]=t;
pa=son;
}else break;
}
}
return rv;
}
对整体的插入/查询:
void putt(int x){
put(x,1);
if(x==heap[1][1]){
get(1);
put(x,2);
int t=get(2);
put(t,1);
}
}
int gett(){
temp++;
int rv=get(1);
put(rv,2);
return rv;
}
附:跑得飞快的代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstdlib>
#include <cstring>
#include <cmath>
using namespace std;
int read(){
int rv=0,fh=1;
char c=getchar();
while(c<'0'||c>'9'){
if(c=='-') fh=-1;
c=getchar();
}
while(c>='0'&&c<='9'){
rv=(rv<<1)+(rv<<3)+c-'0';
c=getchar();
}
return rv*fh;
}
int heap[200005][3],hsize[3];
int m,n,num[200005],temp;
void put(int x,int i){
heap[++hsize[i]][i]=x;
int son=hsize[i],pa=son>>1;
while(pa>=1){
if(i==1){
if(heap[pa][i]>heap[son][i]){
int t=heap[pa][i];heap[pa][i]=heap[son][i];heap[son][i]=t;
son=pa;
pa>>=1;
}else break;
}else {
if(heap[pa][i]<heap[son][i]){
int t=heap[pa][i];heap[pa][i]=heap[son][i];heap[son][i]=t;
son=pa;
pa>>=1;
}else break;
}
}
}
int get(int i){
int rv=heap[1][i];
heap[1][i]=heap[hsize[i]--][i];
int pa=1,son;
while(pa<=(hsize[i]>>1)){
if(i==1) son=heap[pa<<1][i]<heap[pa<<1|1][i]?pa<<1:pa<<1|1;
else son=heap[pa<<1][i]>heap[pa<<1|1][i]?pa<<1:pa<<1|1;
if(i==1){
if(heap[pa][i]>heap[son][i]){
int t=heap[pa][i];heap[pa][i]=heap[son][i];heap[son][i]=t;
pa=son;
}else break;
}else {
if(heap[pa][i]<heap[son][i]){
int t=heap[pa][i];heap[pa][i]=heap[son][i];heap[son][i]=t;
pa=son;
}else break;
}
}
return rv;
}
void putt(int x){
put(x,1);
if(x==heap[1][1]){
get(1);
put(x,2);
int t=get(2);
put(t,1);
}
}
int gett(){
temp++;
int rv=get(1);
put(rv,2);
return rv;
}
int f[200005];
int main(){
freopen("in.txt","r",stdin);
m=read();n=read();
for(int i=1;i<=m;i++){
num[i]=read();
}
for(int i=1;i<=n;i++){
f[read()]++;
}
for(int i=1;i<=m;i++){
putt(num[i]);
while(f[i]){
printf("%d\n",gett());
f[i]--;
}
}
/*for(int i=1;i<=10000;i++){
put(rand(),2);
}
for(int i=1;i<=10000;i++){
printf("%d ",get(2));
}*/
fclose(stdin);
return 0;
}
洛谷 [P1801] 黑匣子的更多相关文章
- 洛谷 P1801 黑匣子_NOI导刊2010提高(06)(未完)
P1801 黑匣子_NOI导刊2010提高(06) 题目描述 Black Box是一种原始的数据库.它可以储存一个整数数组,还有一个特别的变量i.最开始的时候Black Box是空的.而i等于0.这个 ...
- 洛谷 - P1801 - 黑匣子 - 对顶堆
这道题是提高+省选-的难度,做出来的话对数据结构题目的理解会增加很多. 可以使用一种叫做对顶堆的东西,对顶堆是在线维护第n小的logn的算法.大概的思路是,假如我们要找的是第n小,我们就维护一个大小为 ...
- 洛谷P1801 黑匣子
题目传送门 分析:这题和另外一个题目中位数非常相似,有兴趣可以先看看,比这一题简单.首先暴力模拟还是别想了,估计30%的数据都有点悬.正解应该是用二叉堆.但是如果用一个堆当然不方便,所以建两个堆,一个 ...
- [洛谷P1801]黑匣子_NOI导刊2010提高(06)
题目大意:两个操作:向一个可重集中加入一个元素:询问第$k$大的数($k$为之前询问的个数加一) 题解:离散化,权值线段树直接查询 卡点:无 C++ Code: #include <cstdio ...
- 洛谷 P1801 黑匣子_NOI导刊2010提高(06)
题目描述 Black Box是一种原始的数据库.它可以储存一个整数数组,还有一个特别的变量i.最开始的时候Black Box是空的.而i等于0.这个Black Box要处理一串命令. 命令只有两种: ...
- 洛谷 P1801 黑匣子_NOI导刊2010提高(06) 题解
昨晚恶补了一下二叉堆的内容 然后就找了几个二叉堆的题来做awa 然后发现用二叉堆做这题复杂度是O(nlogn) 但是有O(n)的解法 (某大佬这么说) 思路大概就是: 利用一个大根堆一个小根堆来维护第 ...
- 洛谷 P1801 黑匣子 题解
题面 离线处理: 大体思路就是将数组排序,然后对于第k次询问把不可行的数打上标记,然后从头开始寻找第k个没打标记的点的值(排序后的数组保证了它是第k小的). 实现方法:首先离散化原始数组,得到数组fi ...
- 【洛谷P1801】黑匣子
黑匣子 题目链接 看到题解中“维护两个堆”,突然想到了这道题的解法 维护两个堆:大根堆h1, 小根堆h2 大根堆里的是最小的i个值,小根堆里是剩下的值 每Add一个值时 插入到小根堆中, 再比较小根堆 ...
- 「洛谷 P1801」黑匣子
好像很久没有更过博客了,因为博主这几周很忙.其实是在搞颓. 题意很难懂,所以就不重复了.其实是懒. 一眼看上去这是个 \(Splay\) 裸题,直接插入一个数,查询区间第 \(K\) 大,但是这样太不 ...
随机推荐
- hdu_1030(数学题+找规律)
规律就是两个数字的level差+left差+right差 代码: #include<cstdio> #include<iostream> #include<cstring ...
- android仿漫画源码、抽奖转盘、Google相册、动画源码等
Android精选源码 android实现仿今日头条的开源项目 波浪效果,实现流量的动态显示 美妆领域的app, 集成了摄像头取色, 朋友圈, 滤镜等 android仿漫画源码 android一个视差 ...
- reduceByKeyLocally
2017年3月15日, 星期三 reduceByKeyLocally--Transformation类算子 代码示例
- 分享给有需要的你,精选了10套web开发免费视频教程~~
在这里给大家精选百度传课里的一些比较好的视频教程,比较适合新手们,有需要的可以收藏着学习!! 蓝鸥微信小程序全方位深度解析 链接:http://www.chuanke.com/v4702151-19 ...
- file_get_contents("php://input")的使用方法
$data = file_get_contents("php://input"); //input 是个可以访问请求的原始数据的只读流. POST 请求的情况下,最好使用 php: ...
- vue 开发2017年变化回顾及2018年展望
vue.js 变化 从 github 的发布记录我们可以看到2017年 vue.js 的第一个发布为 v2.1.9,最后一个为 v2.5.13,主要发布小版本 2.2~2.5.这些发布提升了vue 与 ...
- 使用 EclEmma 进行覆盖测试
开源软件测试工具 EclEmma,它能够对由 Java 语言编写的程序进行覆盖测试,从而对程序运行的结果生成详尽的覆盖测试报告. UT-Junit 安装 EclEmma 插件 安装 EclEmma 插 ...
- java中的nextLine
package scanner; import java.util.Scanner; public class NextLine { public static void main(String[] ...
- java8-新特性--(接口的默认方法与静态方法)
Java 8用默认方法与静态方法这两个新概念来扩展接口的声明. public interface Inte{ void method(); default void defaultMethod(){ ...
- xen虚拟机(Centos6.6)的创建和扩容
好久没来更博了,从这篇开始,我准备好好梳理一下Hadoop的那些"事".本人技术渣一枚,只是本着知识共享的原则,希望将我所掌握的知识分享出来.若文中有错误的地方,欢迎大家告知我,我 ...