黑匣子(对顶堆

Posted hhyx

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了黑匣子(对顶堆相关的知识,希望对你有一定的参考价值。

# 题意
在最开始,黑盒子是空的,并且i=0。
现在对黑盒子进行一系列的操作处理,操作包括以下两种:
1、ADD(x):表示将x加入到黑盒子中。
2、GET:使i增加1,输出黑盒子中第i小的数值(即将所有数按升序排序后的第i个数)。
下面给出一个具体例子:

技术图片

为了方便描述,下面我们定义两个序列:
1、A表示:这个序列由加入到黑盒子内的所有元素按加入顺序排列后得到,上例中的A序列为(3,1,-4,2,8,-1000,2)。
2、u(1),u(2),…,u(N): 这个序列的第i项表示的是第i次GET操作时,盒子内元素的数量。上例中的u序列为(1,2,6,6)。
根据给出的序列A和u求出操作过程中输出的所有数值。

# 题解
对顶堆,一个大根堆存储当前不会输出的 i-1 个元素,小根堆存的是当前应输出位置往后的元素,

保证大根堆中的元素始终小于根堆中的元素,因为只需要输出所有get操作应该输出的

所以当储存get操作的序列为完成时一直进行操作,

每次完成插入操作时候后进行检查,只有当大根堆空的时候或者大根堆的堆顶小于小根堆的堆顶的时候进行交换,

否则插入到大根堆,将插入后的堆顶移动到小根堆

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N=3e4+10;
 4 int a[N],b[N];
 5 int main(){
 6    int n,m;
 7    priority_queue<int>left;
 8    priority_queue<int,vector<int>,greater<int>>right;
 9    cin>>m>>n;
10    for(int i=0;i<m;i++)
11       cin>>a[i];
12    for(int i=0;i<n;i++)
13       cin>>b[i];
14    sort(b,b+n);
15    int i=0,j=0;
16    while(j < n){
17       while(i == b[j]){//因为i的下标从0开始,而要记录个数,所以每次先判断后加入
18          // 加入后有1个元素,i变为1下次直接判断
19          cout << right.top()<<endl;
20          left.push(right.top());
21          right.pop();
22          j++;
23       }
24       int x=a[i];
25       if(left.empty() || x > right.top())
26          right.push(x);
27       else{//x有可能小于右边的端点,但是大于左边的端点所以先加入左边将最大的放到右边即可
28          left.push(x);
29          right.push(left.top());
30          left.pop();
31       }
32       i++;
33    }
34 }

 

以上是关于黑匣子(对顶堆的主要内容,如果未能解决你的问题,请参考以下文章

对顶堆与应用

浅谈对顶堆

P1168 中位数(对顶堆)

poj 3784(对顶堆)

106. 动态中位数经典 / 对顶堆

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