对顶堆 可以动态维护一个序列上第$k$大的数,k值会发生变化。比写 线段树 或 BST简单。
对顶堆由一个大根堆与一个小根堆组成,小根堆维护前k大的数(包含第$k$个),大根堆维护比第$k$大数小的数。
1.插入:若插入的元素 之小根堆堆顶元素,则将其插入小根堆,否则将其插入大根堆。
2.维护:当小根堆的大小$>k$时,不断将小根堆堆顶元素取出并插入大根堆,直到小根堆的大小等于$k$;当小根堆的大小小于$k$时,不断将大根堆堆顶元素取出并插入小根堆,直到小根堆的大小等于$k$。
3.查询第$k$大元素:小根堆堆顶元素。
4.删除第$k$大元素:删除小根堆堆顶元素。
参考代码:
priority_queue<int> a; // 大根堆
priority_queue<int, vector<int>, greater<int>> b; // 小根堆
for (int i = 0; i < n; ++i) {
int x;
cin >> x;
if (b.empty() || x >= b.top()) b.push(x); // 插入小根堆
else a.push(x); // 插入大根堆
// 调整优先队列的大小
while (b.size() > k) a.push(b.top()),b.pop();
while (b.size() < k) b.push(a.top()),a.pop();
// 输出第 k 小的元素
cout << b.top() << endl;
b.pop();//删除
}
—— 本文来自火龙信奥(义乌睿码科技):义乌青少年信息学奥赛与编程教育平台,专注 CSP-J/S、NOIP、GESP 竞赛培训,线上线下融合教学,助力编程升学。网址:hlcoding.com