有n个数,求这n个数排序后的中间数,如果n为奇数,中间数即为排序后中间那个元素,如果n为偶数就是中间两个元素的平均数。
由于内存只有1M,所以无法存下所有数值进行排序,因此,考虑将n/2+1个元素放入一个优先队列(堆)中,然后每次将剩下的元素逐个放进优先队列中并抛出堆中最大的元素。
这样以后如果n为奇数,队首元素即为中间数;如果是偶数,那么先记录队首元素,再抛出队首元素,原队首与当前队首元素之和除以2就是中间数。
但是如果维护一个优先队列还是会MLE,需要换用make_heap,push_heap和pop_heap函数。
void make_heap (RandomAccessIterator first, RandomAccessIterator last);
void make_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp );
将迭代器[first, last)范围内的元素按堆序排序,默认生成最大堆(大根堆)
注:The element with the highest value is always pointed by first. The order of the other elements depends on the particular implementation, but it is consistent throughout all heap-related functions of this header.
最大值一定在堆顶,剩余元素的顺序依赖于具体的实施。
void push_heap (RandomAccessIterator first, RandomAccessIterator last);
void push_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
调用push_heap时认为[fitst, last-1)区间内为一个有效堆,然后将last-1指向的元素放入堆中。
void pop_heap (RandomAccessIterator first, RandomAccessIterator last);
void pop_heap (RandomAccessIterator first, RandomAccessIterator last, Compare comp);
调用pop_heap时将堆顶的元素移到last-1的位置上,即移出原来的堆,再在[first, last-1)范围内重新建堆。
在我尝试使用vector依然MLE之后,选择了用数组代替,这样需要稍微改变一下,放入剩余元素时先比较一下待入堆元素是否小于堆顶元素,如果是就pop_heap并用新值覆盖原来的堆顶元素,然后push_heap。
#include <cstdio>
#include <vector>
#include <algorithm>
using namespace std;
const int maxn = 250000;
int a[maxn/2+5];
int main(int argc, char const *argv[]) {
int n;
double ans;
scanf("%d", &n);
for (int i = 0; i < n / 2 + 1; i++) {
scanf("%d", &a[i]);
}
make_heap(a, a + n / 2 + 1);
for (int i = n / 2 + 1; i < n; i++) {
int val;
scanf("%d", &val);
if (val < a[0]) {
pop_heap(a, a + n / 2 + 1);
a[n/2] = val;
push_heap(a, a + n / 2 + 1);
}
}
if (n & 1) {
ans = a[0];
} else {
ans = a[0];
pop_heap(a, a + n / 2 + 1);
ans += a[0];
ans /= 2;
}
printf("%.1f\n", ans);
return 0;
}
这道题同时给了我一些思考,STL中的priority_queue事实上也调用了make_heap,那么是不是可以说,优先队列就是一些元素按某种堆序排列后组成的队列?
附STL priority_queue源码:
// TEMPLATE CLASS priority_queue
template < class _Ty,
class _Container = vector<_Ty>,
class _Pr = less<typename _Container::value_type> >
class priority_queue
{
// priority queue implemented with a _Container
public:
typedef _Container container_type;
typedef typename _Container::value_type value_type;
typedef typename _Container::size_type size_type;
typedef typename _Container::reference reference;
typedef typename _Container::const_reference const_reference;
priority_queue()
: c(), comp()
{
// construct with empty container, default comparator
}
explicit priority_queue(const _Pr &_Pred)
: c(), comp(_Pred)
{
// construct with empty container, specified comparator
}
priority_queue(const _Pr &_Pred, const _Container &_Cont)
: c(_Cont), comp(_Pred)
{
// construct by copying specified container, comparator
make_heap(c.begin(), c.end(), comp);
}
template<class _Iter>
priority_queue(_Iter _First, _Iter _Last)
: c(_First, _Last), comp()
{
// construct by copying [_First, _Last), default comparator
make_heap(c.begin(), c.end(), comp);
}
template<class _Iter>
priority_queue(_Iter _First, _Iter _Last, const _Pr &_Pred)
: c(_First, _Last), comp(_Pred)
{
// construct by copying [_First, _Last), specified comparator
make_heap(c.begin(), c.end(), comp);
}
template<class _Iter>
priority_queue(_Iter _First, _Iter _Last, const _Pr &_Pred,
const _Container &_Cont)
: c(_Cont), comp(_Pred)
{
// construct by copying [_First, _Last), container, and comparator
c.insert(c.end(), _First, _Last);
make_heap(c.begin(), c.end(), comp);
}
bool empty() const
{
// test if queue is empty
return (c.empty());
}
size_type size() const
{
// return length of queue
return (c.size());
}
const_reference top() const
{
// return highest-priority element
return (c.front());
}
reference top()
{
// return mutable highest-priority element (retained)
return (c.front());
}
void push(const value_type &_Pred)
{
// insert value in priority order
c.push_back(_Pred);
push_heap(c.begin(), c.end(), comp);
}
void pop()
{
// erase highest-priority element
pop_heap(c.begin(), c.end(), comp);
c.pop_back();
}
protected:
_Container c; // the underlying container
_Pr comp; // the comparator functor
};