【NOI导刊2010】黑匣子的题解——堆的应用

题目:luogu1801.

这道题就是说,维护一个序列的两种操作:

1.插入一个数.

2.k+1之后查询这串序列的第i小.

注:开始k为0.

所以这道题是如何用堆来维护的呢?

我们可以维护两个堆,一个大根堆和一个小根堆,初始时都为空,然后我们把大根堆作为序列比第k个数小的那一段,吧小根堆作为另一段.

那么我们就可以维护这道题了,在操作1时将这个数与大根堆的堆顶比较,若插入的书更大,则插入到后面的小根堆中,否则将大根堆堆顶弹出插入到小根堆中,再将输入的数插入大根堆中.

操作2时直接把小根堆堆顶弹出就可以了.

那么代码如下:

#include<bits/stdc++.h>
using namespace std;
#define TLE priority_queue
int n,m,a[200001],b[200001];
void into(){
  scanf("%d%d",&m,&n);
  for (int i=1;i<=m;i++) scanf("%d",&a[i]);
  for (int i=1;i<=n;i++) scanf("%d",&b[i]);
  sort(b+1,b+1+n);
}
TLE<int>maxq;
TLE<int,vector<int>,greater<int> >minq;
int main(){
  into();
  int k=1,j=1;
  for (int i=1;i<=m;i++){
    if (k==1||maxq.top()<=a[i]) minq.push(a[i]);
    else {minq.push(maxq.top());maxq.pop();maxq.push(a[i]);}
    while (b[j]==i){
      printf("%d\n",minq.top());
      maxq.push(minq.top());minq.pop();
      j++;k++;
    }
  }
  return 0;
}

这是早期作品,具体是怎么样的本人也不记得了,但是思路就是这样的,可能有一些细节上的问题.

猜你喜欢

转载自blog.csdn.net/hzk_cpp/article/details/80537738