The Med(对顶堆动态求解序列中位数)

该博客介绍了如何利用对顶堆解决编程问题,具体是计算给定非负整数序列的连续奇数个数的中位数。作者提供了两种C++实现方式,一种是将最大值放在大根堆顶部,另一种是将目标值放在小根堆顶部,确保在每个阶段都能快速获取中位数。这两种方法的时间复杂度都是O(nlogn),适用于不同数据规模的输入。
摘要由CSDN通过智能技术生成

The Median

题目描述

给出一个长度为 N N N的非负整数序列 A i A_i Ai,对于所有 1 ≤ k ≤ ( N + 1 ) / 2 1 ≤ k ≤ (N + 1) / 2 1k(N+1)/2,输出 A 1 , A 1 ∼ A 3 , … , A 1 ∼ A 2 k − 1 A_1, A_1 \sim A_3, …,A_1 \sim A_{2k - 1} A1,A1A3,,A1A2k1的中位数。即前 1 , 3 , 5 , … 1,3,5,… 1,3,5,个数的中位数。

输入格式

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

2 2 2行包含 N N N个非负整数 A i ( A i ≤ 1 0 9 ) A_i (A_i ≤ 10^9) Ai(Ai109)

输出格式

( N + 1 ) / 2 (N + 1) / 2 (N+1)/2行,第 i i i行为 A 1 , A 3 , … , A 2 k − 1 A_1, A_3, …, A_{2k - 1} A1,A3,,A2k1的中位数。

样例 #1

样例输入 #1

7
1 3 5 7 9 11 6

样例输出 #1

1
3
5
6

提示

对于 20 % 20\% 20%的数据, N ≤ 100 N ≤ 100 N100

对于 40 % 40\% 40%的数据, N ≤ 3000 N ≤ 3000 N3000

对于 100 % 100\% 100%的数据, N ≤ 100000 N ≤ 100000 N100000

题目来源

题意:

给出一个长度为 N N N的非负整数序列 A i A_i Ai,输出前 1 , 3 , 5 , … 1,3,5,… 1,3,5,个数的中位数。

思路:

结合 黑匣子 的思想(对顶堆做法

对于一个 含有 n (奇数)个元素的序列,其 中位数 显然为 n + 1 >> 1 大值,而 对顶堆 可用于 动态求整个序列的第 k 大值。那么做法就不难想到了。总的时间复杂度 O ( n l o g n ) O(nlogn) O(nlogn)

本题又是一道 对顶堆模板题,上代码。

代码 I:(将目标值放在大根堆堆顶)

#define _CRT_SECURE_NO_WARNINGS 1
#include <bits/stdc++.h>

using namespace std;
#define int long long
const int N = 1e5 + 10;
int a[N];
int n;

signed main()
{
	int T = 1; //cin >> T;

	while (T--)
	{
		cin >> n;
		for (int i = 1; i <= n; ++i)
		{
			scanf("%lld", &a[i]);
		}

		priority_queue<int> max_heap;
		priority_queue<int, vector<int>, greater<int>> min_heap;

		for (int i = 1; i <= n; ++i)
		{
			max_heap.push(a[i]);
			
			if (i & 1)
			{
				int k = i + 1 >> 1;
				if (max_heap.size() > k && max_heap.size())
				{
					min_heap.push(max_heap.top());
					max_heap.pop();
				}
				printf("%lld\n", max_heap.top());
				if (max_heap.size() < k + 1 && min_heap.size())
				{
					max_heap.push(min_heap.top());
					min_heap.pop();
				}
			}
			else
			{
				int k = i + 2 >> 1;
				if (max_heap.size() > k && max_heap.size())
				{
					min_heap.push(max_heap.top());
					max_heap.pop();
				}
			}

		}
	}

	return 0;
}

代码 II:(写法更简便,将目标值放在小根堆堆顶)

#include <bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int a[N];
int main()
{
	int n;
	cin>>n;
	
	for(int i=1;i<=n;i++)
	{
		cin>>a[i];
	}
	
	priority_queue<int,vector<int>,greater<int>> heap1;
	priority_queue<int,vector<int>,less<int>>heap2;
	
	int limit=(int)(n+1)/2;
	int co=0;  
	for(int i=1;i<=n;i++)
	{
		heap1.push(a[i]);
		while(heap1.size()>co)
		{
			auto t=heap1.top();
			heap1.pop();
			heap2.push(t);
		}
		
		if(i%2!=0)
		{
			cout<<heap2.top()<<endl;
			heap1.push(heap2.top());
			heap2.pop();
			co++;
		}
	}
	
	
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值