【NOI導刊2010】黑匣子的題解——對頂堆的應用
阿新 • • 發佈:2019-02-12
這道題就是說,維護一個序列的兩種操作:
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; }
這是早期作品,具體是怎麼樣的本人也不記得了,但是思路就是這樣的,可能有一些細節上的問題.