洛谷 [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\) 大,但是这样太不 ...
随机推荐
- [bzoj2288][POJ Challenge]生日礼物
用堆维护双向链表来贪心... 数据范围显然不容许O(nm)的傻逼dp>_<..而且dp光是状态就n*m个了..显然没法优化 大概就会想到贪心乱搞了吧...一开始想贪心地通过几段小的负数把正 ...
- c语言函数实参与形参整理
- JEECG 3.7.2版本发布,企业级JAVA快速开发平台
JEECG 3.7.2版本发布 - 微云快速开发平台 JEECG是一款基于代码生成器的J2EE快速开发平台,开源界"小普元"超越传统商业企业级开发平台.引领新的开发模式(Onli ...
- html日历(1)
<html> <head> <link rel="stylesheet" type="text/css" href="S ...
- 详解String类中的intern()方法
我们用一个经典的例子来理解 package com.jvm.heap; public class MyTest { public static void main(String[] args) { S ...
- TIJ笔记:内部类的初始化
看编程思想有点时间了,看到了些在马士兵老师没有讲过的部分,所以打算记录一下 内部类的初始化: .内部类的初始化和外部类的初始化略有不同,可以使用 外部类对象.new 内部类对象 创建内部类对象 pac ...
- javascript alert乱码的解决方法
http://www.jb51.net/article/42805.htm 提示时中文乱码,拼音什么的都没有问题呀,下面我在论坛找到一解决办法,下面与大家分享. 解决办法一: 复制代码 代码如下: e ...
- 风险案例-28期-项目Leader与团队成员缺乏沟通,问题响应度较慢导致团队士气低落,工作效率低
典型案例: A公司某C类项目目前进入开发高峰期,项目组的三个leader预计在项目的实际task投入占比为70%,剩30%工作时间用于指导组员进行作业实施并担当部分管理工作.从项目实施过程中发现Lea ...
- 动态添加div及对应的js、css文件
动态添加div及对应的js.css文件 在近期的项目开发中需要在首页中添加很多面板型的div,直接加载代码显得很繁琐,于是利用js封装一个动态添加div及其对应css文件和js文件的方法供大家参考使用 ...
- linux libpcap的性能问题,请大家注意绕行。
内核代码中,ip_rcv是ip层收包的主入口函数,该函数由软中断调用.存放数据包的sk_buff结构包含有目的地ip和端口信息,此时ip层进行检查,如果目的地ip不是本机,且没有开启转发的话,则将包丢 ...