题解【黑匣子_NOI导刊2010提高(06)】(洛谷P1801)
题目大意
给出一个长度为\(M\)序列\(A\),表示第\(i\)回合将\(A_i\)放入一个箱子中(共有\(M\)回合),再给出一个长度为\(N\)序列\(B\),表示在\(B_i\)回合执行一次\(Get\)操作。\(Get\)操作:\(k++\),然后输出箱子中第\(k\)大的元素;\(k\)初始为\(0\)。
分析一下
啊箱子就是堆啦- 假设正在进行第\(B_i\)回合,就是要将\(A_{B_i}\)放进箱子中,然后再输出箱子中第\(i\)小的元素。
- 对于箱子中第\(i\)小的元素,其左边的元素(第\(i-1\cdots 1\)小)全部比其小,且依次变小,符合大根堆的特性;
- 其右边的元素(第\(i +1\cdots M\)小)全部比其大,且依次变大,符合小根堆的特性。
- 那么我们可以用一个大根堆与一个小跟堆来维护箱子里面的元素。将每次要求的答案放在小根堆(当然大根堆也可以)的堆顶。
- 可以发现,大根堆中的元素个数始终为\(i-1\)。
操作流程
- 首先外循环枚举\(B\)序列。将\(A\)序列中的元素塞进大根堆中。
- 维护大根堆中的元素只能有\(i-1\)个,即每当个数超出时,将大根堆的堆顶移至小根堆中。
- 输出小根堆的堆顶(即答案)。因为这个答案已经贡献完了,所以再将其塞回至大根堆中。