poj3784(对顶堆)
题意:多组数据,让你求出1~i(i为奇数&&i<=n)的中位数
思路:首先复杂度必为O(n)或O(nlogn)的(数据范围)
思索,如果题目要求1次中位数,好求!排个序,取a[(n+1)/2]就好了 [这道题n的前提是奇数哈]
可是???要求多次中位数,而且是每次加入两个数后,再求一次?
别慌!!!已知中位数的性质是跟数值的顺序有关的。
顺序?大家想一想有哪个数据结构能够动态维护数列顺序,并1次操作复杂度在O(logn)之内
那当然是堆【肯定用优先队列啦】^_^
方式:【对顶堆】
不要太在乎为何叫“对顶堆”,因为我也不知道
通过取中间的数,可以想到维护两个堆:一个大根堆(叫她Qx),一个小根堆(叫他Qn),这两个堆的大小无论怎样动态变化都恒保持:Qx.size()-Qn.size()=1或0 [Qx.size()总是>=Qn.size()的]
要两个堆的目的大家肯定都能想到了,因为一旦i为奇数要输出时,直接输出Qx.top()就好了。不过这只是脑补出了一些过程,请看下面:

我说的有点啰嗦,大家还是看看代码吧:
#include<stdio.h>
#include<algorithm>
#include<queue>
using namespace std;
priority_queue<int> Qx;
priority_queue<int,vector<int>,greater<int> > Qn;
int main() {
// freopen("poj3785.out","w",stdout);
int t;
scanf("%d",&t);
while(t--) {
while(!Qn.empty()) Qn.pop();
while(!Qx.empty()) Qx.pop();
int p,n; scanf("%d%d",&p,&n);
printf("%d %d\n",p,(n+1)/2);
for(int i=1;i<=n;i++) {
int b; scanf("%d",&b);
//之所以要加上特判,因为要保证两个队列都非空,才能不运行错误
if(i==1) {
Qx.push(b); printf("%d ",b);
}
else if(i==2) {
if(b<Qx.top()) Qn.push(Qx.top()),Qx.pop(),Qx.push(b);
else Qn.push(b);
}
else if(Qx.size()==Qn.size()) { //Qx.size()必须+1
if(b<=Qn.top()) Qx.push(b);
else { //b>Qn.top()
Qx.push(Qn.top()); Qn.pop(); Qn.push(b); //将小根堆的堆头插入大根堆,并将b插入小根堆
}
printf("%d ",Qx.top());
if(((i+1)/2)%10==0) printf("\n");
}
else { //Qn.size()必须+1
if(b>=Qx.top()) Qn.push(b);
else { //b<Qx.top();
Qn.push(Qx.top()); Qx.pop(); Qx.push(b); //有没有觉得是15行的反操作呢?
}
}
}
if((n+1)/2%10!=0) printf("\n");
}
return 0;
}
有什么建议,欢迎讨论
poj3784(对顶堆)的更多相关文章
- poj3784 Running Median[对顶堆]
由于我不会讲对顶堆,所以这里直接传上一个巨佬的学习笔记. 对顶堆其实还是很容易理解的,想这题的时候自己猜做法也能把没学过的对顶堆给想出来.后来了解,对顶堆主要还是动态的在线维护集合$K$大值.当然也可 ...
- hdu3282 链表或者对顶堆
维护序列的动态中位数 第一次用链表做题..感觉指针指来指去也挺麻烦的.. 本题链表解法就是用数组模拟出一个链表,然后离线输入所有数,排序,按照输入顺序在链表里删除元素,一次性删掉两个,然后中位数指针对 ...
- 【uoj#280】[UTR #2]题目难度提升 对顶堆+STL-set
题目描述 给出 $n$ 个数 $a_1,a_2,...,a_n$ ,将其排为序列 $\{p_i\}$ ,满足 $\{前\ i\ 个数的中位数\}$ 单调不降.求字典序最大的 $\{p_i\}$ . 其 ...
- hdu4261 Estimation[暴力dp+对顶堆]
https://vjudge.net/problem/HDU-4261 对于一个长2000的数列划分最多25个块,每块代价为块内每个数与块内中位数差的绝对值之和,求最小总代价. 套路化地,设$f[i] ...
- 【POJ 3784】 Running Median (对顶堆)
Running Median Description For this problem, you will write a program that reads in a sequence of 32 ...
- P1168 中位数(对顶堆)
题意:维护一个序列,两种操作 1.插入一个数 2.输出中位数(若长度为偶数,输出中间两个较小的那个) 对顶堆 维护一个小根堆,一个大根堆,大根堆存1--mid,小根堆存mid+1---n 这样堆顶必有 ...
- 洛谷 - P1801 - 黑匣子 - 对顶堆
这道题是提高+省选-的难度,做出来的话对数据结构题目的理解会增加很多. 可以使用一种叫做对顶堆的东西,对顶堆是在线维护第n小的logn的算法.大概的思路是,假如我们要找的是第n小,我们就维护一个大小为 ...
- bzoj 1112: [POI2008]砖块Klo【对顶堆】
priority_queue实现的对顶堆,细节超级多WA了十几次--但是理论上是最简便的orz其实是我已经不会写平衡树了 枚举左端点,显然要把这一段的高度搞成(l,l+k-1)的高度中位数,所以需要一 ...
- 【Luogu P1168】【Luogu P1801&UVA 501】中位数&黑匣子(Black Box)——对顶堆相关
Luogu P1168 Luogu P1801 UVA 501(洛谷Remote Judge) 前置知识:堆.优先队列STL的使用 对顶堆 是一种在线维护第\(k\)小的算法. 其实就是开两个堆,一个 ...
随机推荐
- ES6-11学习笔记--数值的扩展
二进制 0B 八进制 0O Number.isFinite() , Number.isNaN() Number.parseInt() , Number.parseFloat() Number ...
- 常用 adb 命令总结
1. 显示当前运行的全部模拟器: adb devices 2. 安装应用程序: adb install -r 应用程序.apk 3. 获取模拟器中的文件: a ...
- java基础-多线程线程池
线程池 * 程序启动一个新线程成本是比较高的,因为它涉及到要与操作系统进行交互.而使用线程池可以很好的提高性能,尤其是当程序中要创建大量生存期很短的线程时,更应该考虑使用线程池.线程池里的每一个线程代 ...
- 文件IO-Properties
java.lang.Object 继承者 java.util.Dictionary<K,V> 继承者 java.util.Hashtable<Object,Object> 继承 ...
- 基于LAMP离线部署zabbix3.2.11
zabbix是个什么东西这里不再赘述,先安装lamp再安装zabbix. 1. 安装依赖插件(把下面PHP那些依赖库全部都装了) #yum install -y gcc gcc-c++ opens ...
- JavaScript学习总结2-对象
JavaScript中对象除了最后一个属性以外都在结尾加逗号,同时所有属性都要在{ }内 1 <!DOCTYPE html> 2 <html lang="en"& ...
- rabbitmq简单运用
<?php /** * 生产者 */ $connection = new AMQPConnection([ 'host' => '192.168.23.130', 'port' => ...
- AcWing周赛43
AcWing周赛43 题源:https://www.acwing.com/activity/content/1233/ 4314. 三元组 直接暴力做就是了,我一开始还在找规律..悲 我滴代码 #in ...
- Confluent之Kafka Connector初体验
概述 背景 Apache Kafka 是最大.最成功的开源项目之一,可以说是无人不知无人不晓,在前面的文章<Apache Kafka分布式流处理平台及大厂面试宝典>我们也充分认识了Kafk ...
- Linux中信号量的实现
如果一个任务获取信号量失败,该任务就必须等待,直到其他任务释放信号量.本文的重点是,在Linux中,当有任务释放信号量之后,如何唤醒正在等待该信号量的任务. 信号量定义如下: struct semap ...