【POJ1442】Black Box

这道题可以用Splay、fhq-treap解决,但是平衡树解这道题大材小用,所以我采用了对顶堆解决。

考虑建立两个堆:以i为分割点,用大根堆存储前半段序列,用小根堆存储后半段序列。我们控制大根堆的元素个数为i,这样查询时大根堆的堆顶就是排名为i的元素。然后我们考虑维护对顶堆。

对于add操作,我们先将元素放入下面的大根堆内,从堆顶不断取出元素放到小根堆直到大根堆元素个数为i,这样大根堆的根就是第i小的元素,同时可以保证对顶堆的性质;
同理,对于get操作,我们先输出大根堆的根,然后将小根堆的根移到大根堆(因为i每次加一,要始终保证大根堆有i个元素),这样仍保证对顶堆的性质不变
因此,时间复杂度为O(nlog2n),我们用STL的优先队列即可完成。

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <queue>
 6 using namespace std;
 7 typedef long long ll;
 8 int n,m,a[200010];
 9 priority_queue<int> maxx;
10 priority_queue<int,vector<int>,greater<int> >minn;
11 int main() {
12     scanf("%d%d",&n,&m);
13     for(int i=1;i<=n;i++)
14         scanf("%d",&a[i]);
15     int now=1;
16     for(int i=1;i<=m;i++) {
17         int x;
18         scanf("%d",&x);
19         for(int j=now;j<=x;j++) {
20             maxx.push(a[j]);
21             if(maxx.size()==i) minn.push(maxx.top()),maxx.pop();
22         }
23         now=x+1;
24         printf("%d\n",minn.top());
25         maxx.push(minn.top()); 
26         minn.pop();
27     }
28     return 0;
29 }
AC Code

猜你喜欢

转载自www.cnblogs.com/shl-blog/p/10887188.html
Box