您的位置:首页 > 其它

堆和堆排序

2014-04-26 17:58 183 查看
这个题大意是有一个数据结构支持两种操作A与Get操作,其中A
x表示插入x. Get i表示返回结构中的第i小的数.给你A和Get操作的顺序和参数,现在要你对每个Get输出值.

取前u(i)个数排序~
然后取第i个数~(i=1,2,3……)
后来发现可以用大顶堆和小顶堆做~
每次将u(i)个数存入小顶堆中~
取小顶堆堆顶元素存入大顶堆中~
删除堆顶元素~
将大顶堆堆顶元素存入小顶堆中删除堆定元素~
这样大顶堆中的元素个数不变~
总是最小的前i个~

题解:每次取第k小元素,k不断更新。使用两个堆,来完成。
小顶堆负责选出最小的元素,大顶堆负责选出k个元素中最大的元素,即第k小元素 

大顶堆的堆顶元素始终小于小顶堆的堆顶元素,这样的话大顶堆中的所有元素都小于小顶堆中的元素,如果大顶堆中有k-1个元素,那么小顶堆的堆顶元素就是要找的
第k小 元素了

Sample Input
7 4                                         ( n,m,分别是a数组,u数组的元素个数)

3 1 -4 2 8 -1000 2               (a数组)

1 2 6 6  (数u[i]w为几就加到a几,然后输出第i 小的:输出数组a前1个第1小的,前两个第2小的,前6个第3小的,前6个第4小的)

Sample Output
3

3

1

2

大根堆分别有1、2、3、4个元素   3 ,3   1,3  1 -4 2 8 -1000,3 1 -4 2 8 -1000。。。。3,3 1,1 -4 -1000,1 -4 2 -1000。。。。_,1, -4 -1000,1 -4  -1000
小顶堆元素为 3,3,3 1 2 8,3 2 8  即负责选出最小元素

#include<iostream>
#include<stdio.h>
#include<queue>
#include<string.h>
using namespace std;

const int maxint=30010;

int num[maxint];
int query[maxint];

priority_queue<int ,vector <int> ,less<int> >p2;//大根堆
priority_queue<int ,vector <int> ,greater<int> >p1;//小根堆

int main()
{
int m,n,i,j,k;
int temp;
while(scanf("%d%d",&m,&n)!=EOF)
{
for(i=0;i<m;i++)
scanf("%d",&num[i]);
for(i=0;i<n;i++)
scanf("%d",&query[i]);
//输入结束之后,就是从头到尾维护一个大根堆和小根堆
//大根堆中始终存放在查询之前的元素
j=0;
for(i=0;i<m;i++)
{
p2.push(num[i]);//把第i个元素放入大根堆
p1.push(p2.top());//把大根堆的最大元素放入小根堆
p2.pop();
if(query[j]==i+1)//当前询问
{
while(query[j]==i+1)
{
temp=p1.top();//小根堆的最小元素就是第i+1小的元素,因为大根堆中的i个元素
p1.pop();//都小于temp
p2.push(temp);
printf("%d\n",temp);
j++;
}
}
}
}
return 0;
}


题外话丨分治法  直到最后子问题可以简单的直接求解,原问题的解即子问题的解的合并。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: