Running Median POJ - 3784 (对顶堆/优先队列)

For this problem, you will write a program that reads in a sequence of 32-bit signed integers. After each odd-indexed value is read, output the median (middle value) of the elements received so far.

Input

The first line of input contains a single integer P, (1 ≤ P ≤ 1000), which is the number of data sets that follow. The first line of each data set contains the data set number, followed by a space, followed by an odd decimal integer M, (1 ≤ M ≤ 9999), giving the total number of signed integers to be processed. The remaining line(s) in the dataset consists of the values, 10 per line, separated by a single space. The last line in the dataset may contain less than 10 values.

Output

For each data set the first line of output contains the data set number, a single space and the number of medians output (which should be one-half the number of input values plus one). The output medians will be on the following lines, 10 per line separated by a single space. The last line may have less than 10 elements, but at least 1 element. There should be no blank lines in the output.

Sample Input

3
1 9
1 2 3 4 5 6 7 8 9
2 9
9 8 7 6 5 4 3 2 1
3 23
23 41 13 22 -3 24 -31 -11 -8 -7
3 5 103 211 -311 -45 -67 -73 -81 -99
-33 24 56

Sample Output

1 5
1 2 3 4 5
2 5
9 8 7 6 5
3 12
23 23 22 22 13 3 5 5 3 -3
-7 -3

题意:每组M个数,然后对于每组数读入的时候,只要读入了奇数个的数,就求出先前读入数的中位数,然后输出

思路:可以采用两个优先队列的做法,如果当前读入的数>当前中位数,插入小根堆,否则插入大根堆,这样实际上就维护了中位数相邻两侧的值。然后维护 num【小根堆】 - num【大根堆】 <= 1,就是维护中位数两侧的数量应当均分,这样小根堆的top,即是中位数

 1 #include<cstdio>
 2 #include<iostream>
 3 #include<queue>
 4 using namespace std;
 5
 6 int t;
 7 int cas,n;
 8 const int maxn = 1e4+5;
 9 int ans[maxn];
10 int main()
11 {
12     scanf("%d",&t);
13     while(t--)
14     {
15 priority_queue<int,vector<int>,greater<int> >que1;
16 priority_queue<int,vector<int>,less<int> >que2;
17
18         scanf("%d%d",&cas,&n);
19         printf("%d %d\n",cas,n/2+1);
20         int tmp;
21         int l=0,r=0,num=0;
22         int cnt = 0;
23         for(int i=1;i<=n;i++)
24         {
25             scanf("%d",&tmp);
26             if(tmp > num)
27             {
28                 que1.push(tmp);
29                 r++;
30             }
31             else
32             {
33                 que2.push(tmp);
34                 l++;
35             }
36             if(r < l)
37             {
38                 int f = que2.top();
39                 que2.pop();
40                 que1.push(f);
41                 r++,l--;
42             }
43             else if(r > l + 1)
44             {
45                 r--,l++;
46                 int f = que1.top();
47                 que1.pop();
48                 que2.push(f);
49             }
50             num = que1.top();
51             if(i&1)
52             {
53                 ans[++cnt] = num;
54             }
55         }
56         for(int i=1;i<=cnt;i++)
57         {
58             printf("%d",ans[i]);
59             if(i != cnt && i%10!=0)printf(" ");
60             else printf("\n");
61         }
62     }
63 }



原文地址:https://www.cnblogs.com/iwannabe/p/10165305.html

时间: 2024-11-01 13:41:51

Running Median POJ - 3784 (对顶堆/优先队列)的相关文章

Running Median POJ - 3784

本题使用对顶堆做法. 为了动态维护中位数,我们可以建立两个堆 :一个大根对,一个小根堆. 用法:在动态维护的过程中,设当前的长度为length,大根堆存从小到大排名 $1 \thicksim \dfrac{m}{2} $ 的整数,小根堆存小到大排名 $ \dfrac{m}{2} + 1 \thicksim m $ 的整数 如何动态维护?顾名思义,动态,即边输入边处理.显然,为了维护中位数,我们还要不断地维护两个堆的\(size\) 每次新读入一个值,就 \(\begin{cases}插入大根堆&

poj 3784 用堆动态求解中位数

堆真是一种简单而又神奇的数据结构,以前用它求过前kth的数,现在又可以用两个堆来动态求解中位数. 算法: 构建一个大顶堆和一个小顶堆,分别记为g和l. 假设当前中位数为mid,新读入一个数为tmp,则: 1.如果tmp < mid,则将tmp插入大顶堆,跳到步骤3. 2.如果tmp >= mid,则将tmp插入小顶堆,跳到步骤4. 3.如果大顶堆的元素个数比小顶堆多2(两个堆个数不平衡),则将mid插入小顶堆,弹出大顶堆堆顶元素为新的mid. 4.与步骤3相反,如果小顶堆的元素个数比大顶堆多2

POJ 3784 Running Median 动态求中位数 堆

题意. 1000个case 每个case 输入若干个数,对第k个输入,如果k为奇数,则输出前k个数的中位数 那么这就是动态求中位数了 实现的思路也比较简洁 用两个堆, 大顶堆和小顶堆 每次输入一个数,如果这个数比当前的中位数大,就存入小顶堆中,  否则就存入大顶堆. 然后调整, 小顶堆元素的个数要等于大顶堆的元素个数,或者比其多1. 如果小顶堆的元素太多,就塞到大顶堆里,反之亦然 这样一来就会发现.小顶堆的元素比所有大顶堆的元素都大, 而且小顶堆的堆顶就是中位数. 那么怎么样才能想到这样一个思路

poj 3784(对顶堆)

Running Median Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1824   Accepted: 889 Description For this problem, you will write a program that reads in a sequence of 32-bit signed integers. After each odd-indexed value is read, output t

POJ 3784 - Running Median(动态中位数) 题解

此文为博主原创题解,转载时请通知博主,并把原文链接放在正文醒目位置. 题目链接:http://poj.org/problem?id=3784 题目大意: 依次给出n个数字,求在数据输入过程中的所有中位数.(共有(n+1)/2个) 输入格式: 输入一个数字P(1<=P<=1000),表示数据组数. 对于每组数据,第一行输入数据组号和数字总个数(1<=个数<=9999),中间以一个空格隔开. 接下来每行给出至多10个数字. 输出格式: 对于每组数据,第一行输出数据组号和中位数个数,中间

【POJ 3784】 Running Median

[题目链接] http://poj.org/problem?id=3784 [算法] 对顶堆算法 要求动态维护中位数,我们可以将1-M/2(向下取整)小的数放在大根堆中,M/2+1-M小的数放在小根堆中 每次插入元素时,先将插入元素与小根堆堆顶比较,如果比堆顶小,则插入小根堆,否则,插入大根堆,然后,判断两个堆 的元素个数是否平衡,若不平衡,则交换两个堆的堆顶 [代码] #include <algorithm> #include <bitset> #include <ccty

【POJ3784】Running Median

Running Median Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 3406   Accepted: 1576 Description For this problem, you will write a program that reads in a sequence of 32-bit signed integers. After each odd-indexed value is read, output

$Poj3784\ Running\ Median$

Poj Description 动态维护中位数问题 Sol "对顶堆"的在线做法 建立两个二叉堆,一个大根堆一个小根堆 在依次读入这个整数序列的过程中,设当前序列为l,要始终保证: 1.序列中从小到大排名为1~l/2的整数存在大根堆中 2.序列中从小到大排名为l/2+1~l的整数存在小根堆中 每次插入一个数,与之前的中位数相比较,如果较小就插入大根堆,反之.. 必须要维护两个堆中的元素数目相差最多为1,否则取出数目多的堆顶加入另一个堆 小根堆的堆顶即为中位数 最后还有来自gql的两点注

浅谈对顶堆

对顶堆详解 我们知道,堆是一种极有用的数据结构.它能在短时间内将数据维护成单调递增/递减的序列.但是这种"朴素堆"对于问题求解起到的效果毕竟是有限的.所以我们在朴素堆的基础上,进行深入思考和适当变形,使之能解决一些其他的用朴素堆解决不了的问题,并使思路变得简洁有效. 这篇随笔就堆中的一个分支--对顶堆进行讲解,读者在阅读前应该掌握堆的基本概念,以便于更好地理解对顶堆. 如果把堆中的大根堆想成一个上宽下窄的三角形,把小根堆想成一个上窄下宽的三角形,那么对顶堆就可以具体地被想象成一个&qu