P1168 中位数[堆 优先队列]

题目描述

给出一个长度为NNN的非负整数序列AiA_iAi?,对于所有1≤k≤(N+1)/21 ≤ k ≤ (N + 1) / 21≤k≤(N+1)/2,输出A1,A3,…,A2k−1A_1, A_3, …, A_{2k - 1}A1?,A3?,…,A2k−1?的中位数。即前1,3,5,…1,3,5,…1,3,5,…个数的中位数。

输入输出格式

输入格式:

第1行为一个正整数N,表示了序列长度。

第2行包含N个非负整数Ai?(Ai?≤109)。

输出格式:

共2(N+1)/2行,第iii行为A1?,A3?,…,A2k−1?的中位数。

输入输出样例

输入样例#1:

7
1 3 5 7 9 11 6

输出样例#1:

1
3
5
6

说明

对于20%的数据,N≤100;

对于40%的数据,N≤3000;

对于100%的数据,N≤100000。

解析:

解法一:

STL的vector暴力解。

参考代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cstdlib>
 4 #include<ctime>
 5 #include<queue>
 6 #include<vector>
 7 #include<algorithm>
 8 #define N 100010
 9 using namespace std;
10 vector<int> a;
11 int main()
12 {
13     int n,x;
14     cin>>n;
15     for(int i=0;i<n;i++)
16     {
17         scanf("%d",&x);
18         a.insert(upper_bound(a.begin(),a.end(),x),x);
19         if(i%2==0) printf("%d\n",a[(i+1)/2]);
20     }
21     return 0;
22 }

解法二:

这里要引入一种堆的新的打开方式:两个堆维护第k大/小的数。

我们用一个大跟堆存放较小值,一个小根堆存放较大值,也就是说,两个堆保持大根堆中的最大值恒比小根堆中的最小值小这样一种性质。

每次动态向两个堆中放入数值时,我们都要维护它的性质,使得它是第k大的值。

求中位数是这个思路的一个变种。

参考代码:

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<ctime>
 6 #include<cstdlib>
 7 #include<algorithm>
 8 #include<queue>
 9 #include<set>
10 #include<map>
11 using namespace std;
12 priority_queue<int> q;
13 priority_queue<int,vector<int>,greater<int> > p;
14 int main()
15 {
16     int n,x;
17     cin>>n;
18     scanf("%d",&x);
19     q.push(x);
20     printf("%d\n",q.top());
21     for(int i=2;i<=n;i++)
22     {
23         scanf("%d",&x);
24         if(x<q.top()) q.push(x);
25         else p.push(x);
26         while(abs(q.size()-p.size())>1)
27         {
28             if(q.size()>p.size()){
29                 p.push(q.top());q.pop();
30             }
31             else{
32                 q.push(p.top());p.pop();
33             }
34             if(i%2){
35                 if(q.size()>p.size()) printf("%d\n",q.top());
36                 else printf("%d\n",p.top());
37             }
38         }
39     }
40     return 0;
41 }

2019-05-26 17:13:43

原文地址:https://www.cnblogs.com/DarkValkyrie/p/10926669.html

时间: 2024-10-08 20:45:15

P1168 中位数[堆 优先队列]的相关文章

洛谷P1168 中位数 堆

洛谷P1168 中位数   堆 求a[ 1 ] --a[ 1 ] 的中位数 ,a[ 1 ]--a[ 3 ] 的中位数 a[ 1 ]--a[ 5 ] 的中位数 题解1.假设我们已知 a[ 1 ]--a[ i ] 的中位数 (i&1) 此时我们求 a[ 1 ]--a[ i+2 ] 的中位数 那么我们可以把比他大的划到一份中,比他小的划到一份中,如果两份数的个数相同,则其仍然是中位数2.如果不同,比如说 big > small 那我们就把比他大的数 作为中位数 ans 到比中位数小的数中因为原本s

P1168 中位数

P1168 中位数 一个大根堆,一个小根堆.胡乱搞搞就可以了,根据中位数的计算方法. #include<cstdio> #include<iostream> #include<algorithm> struct Min_heap { int tail; int data[100010]; int top() { return data[1]; } void swap(int &a,int &b) { int c=a; a=b; b=c; return ;

堆 (优先队列)举例

*/--> pre.src {background-color: Black; color: White;} 堆 (优先队列)举例 题目: 你需要驾驶一辆卡车行驶 l 单位距离.最开始的时候,卡车上有 p 单位的汽油.卡车每开 1 单位距离需要消费 1 单位的汽油.如果在途中汽车上的汽油耗尽,卡车就无法继续前行,因而无法到达终点.在途中一共有 n 个加油站.第 i 个加油站在距离起点 ai 单位距离的地方,最多可以给卡车加 bi 单位汽油.假设卡车的燃料箱的容量是无限大的,无论加多少油都没有问题

纯数据结构Java实现(6/11)(二叉堆&amp;优先队列)

堆其实也是树结构(或者说基于树结构),一般可以用堆实现优先队列. 二叉堆 堆可以用于实现其他高层数据结构,比如优先队列 而要实现一个堆,可以借助二叉树,其实现称为: 二叉堆 (使用二叉树表示的堆). 但是二叉堆,需要满足一些特殊性质: 其一.二叉堆一定是一棵完全二叉树 (完全二叉树可以用数组表示,见下面) 完全二叉树缺失的部分一定是在右下方.(每层一定是从左到右的顺序优先存放) 完全二叉树的结构,可以简单理解成按层安放元素的.(所以数组是不错的底层实现) 其二.父节点一定比子节点大 (针对大顶堆

堆-优先队列

堆-优先队列 前置知识:二叉树. 参考资料 暂无 堆就是优先队列,可以用来解决动态区间查询最值问题. 堆就是一个完全二叉树,可以插入节点,删除根节点(也可以删除特定节点). 为了方便,普通的堆节点 \(i\) 的父亲就是 \([i\div2]\) (\([x]\) 表示不超过 \(x\) 的最大整数). 节点 \(i\) 的左儿子是 \(i\times2\),右儿子是 \(i\times2+1\). 对于一个大顶堆: 每次插入节点的时候,就把节点插在完全二叉树的最后,如果它比它的父亲节点大,就把

【洛谷】【堆】P1168 中位数

[题目描述:] 给出一个长度为N的非负整数序列A[i],对于所有1 ≤ k ≤ (N + 1) / 2,输出A[1], A[3], -, A[2k - 1]的中位数.即前1,3,5,--个数的中位数. [输入格式:] 输入文件median.in的第1行为一个正整数N,表示了序列长度. 第2行包含N个非负整数A[i] (A[i] ≤ 10^9). [输出格式:] 输出文件median.out包含(N + 1) / 2行,第i行为A[1], A[3], -, A[2i – 1]的中位数. 输入样例#

P1168 中位数(对顶堆)

题意:维护一个序列,两种操作 1.插入一个数 2.输出中位数(若长度为偶数,输出中间两个较小的那个) 对顶堆 维护一个小根堆,一个大根堆,大根堆存1--mid,小根堆存mid+1---n 这样对顶必有中位数. 每次操作后维护两个堆元素数量,保证一个比另一个多1或相等 #include<cstdio> #include<iostream> #include<algorithm> #include<queue> using namespace std; #def

堆--P1168 中位数

题目描述 给出一个长度为N的非负整数序列Ai?,对于所有1≤k≤(N+1)/2,输出A1,A3,…,A2k−1的中位数.即前1,3,5,…个数的中位数. 输入格式 第1行为一个正整数N,表示了序列长度. 第2行包含N个非负整数Ai(Ai≤109). 输出格式 共(N+1)/2行,第i行为A1,A3,…,A2k−1?的中位数. 首先记录一个变量mid,记录答案(中位数).建立两个堆,一个大根堆一个小根堆,大根堆存≤mid的数,小根堆存 >mid的的数. 所以我们向堆中加入元素时,就通过与mid的比

算法-滑动窗口的中位数(堆)

今天在网上刷了一道关于堆的题,感觉有所收获.因为在这里之前,之前从来没有接触过关于堆的题目. 题意: 给定一个包含 n 个整数的数组,和一个大小为 k 的滑动窗口,从左到右在数组中 滑动这个窗口,找到数组中每个窗口内的中位数.(如果数组个数是偶数,则在 该窗口排序数字后,返回第 N/2 个数字.) 样例: 对于数组 [1,2,7,8,5], 滑动大小 k = 3 的窗口时,返回 [2,7,7] 最初,窗口的数组是这样的: [ | 1,2,7 | ,8,5] , 返回中位数 2; 接着,窗口继续向