黑匣子(对顶堆

# 题意
在最开始,黑盒子是空的,并且i=0。
现在对黑盒子进行一系列的操作处理,操作包括以下两种:
1、ADD(x):表示将x加入到黑盒子中。
2、GET:使i增加1,输出黑盒子中第i小的数值(即将所有数按升序排序后的第i个数)。
下面给出一个具体例子:

为了方便描述,下面我们定义两个序列:
1、A表示:这个序列由加入到黑盒子内的所有元素按加入顺序排列后得到,上例中的A序列为(3,1,-4,2,8,-1000,2)。
2、u(1),u(2),…,u(N): 这个序列的第i项表示的是第i次GET操作时,盒子内元素的数量。上例中的u序列为(1,2,6,6)。
根据给出的序列A和u求出操作过程中输出的所有数值。

# 题解
对顶堆,一个大根堆存储当前不会输出的 i-1 个元素,小根堆存的是当前应输出位置往后的元素,

保证大根堆中的元素始终小于根堆中的元素,因为只需要输出所有get操作应该输出的

所以当储存get操作的序列为完成时一直进行操作,

每次完成插入操作时候后进行检查,只有当大根堆空的时候或者大根堆的堆顶小于小根堆的堆顶的时候进行交换,

否则插入到大根堆,将插入后的堆顶移动到小根堆

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 const int N=3e4+10;
 4 int a[N],b[N];
 5 int main(){
 6    int n,m;
 7    priority_queue<int>left;
 8    priority_queue<int,vector<int>,greater<int>>right;
 9    cin>>m>>n;
10    for(int i=0;i<m;i++)
11       cin>>a[i];
12    for(int i=0;i<n;i++)
13       cin>>b[i];
14    sort(b,b+n);
15    int i=0,j=0;
16    while(j < n){
17       while(i == b[j]){//因为i的下标从0开始,而要记录个数,所以每次先判断后加入
18          // 加入后有1个元素,i变为1下次直接判断
19          cout << right.top()<<endl;
20          left.push(right.top());
21          right.pop();
22          j++;
23       }
24       int x=a[i];
25       if(left.empty() || x > right.top())
26          right.push(x);
27       else{//x有可能小于右边的端点,但是大于左边的端点所以先加入左边将最大的放到右边即可
28          left.push(x);
29          right.push(left.top());
30          left.pop();
31       }
32       i++;
33    }
34 }

原文地址:https://www.cnblogs.com/hhyx/p/12541875.html

时间: 2024-11-05 12:10:14

黑匣子(对顶堆的相关文章

黑匣子 对顶堆

黑匣子 对顶堆 对顶堆,由一个小跟堆和一个大根堆组成,且满足小跟堆堆顶大于大根堆堆顶. ------- ----- <-- 小跟堆 --- - - --- ----- <-- 大根堆 ------- 可以看出对顶堆满足从上自下一直递减的性质 黑匣子_NOI导刊2010提高 题面 而这道题要维护第\(i\)小,即是让我们维护一个对顶堆,使大根堆大小为\(i-1\),小跟堆的堆顶即是第\(i\)小. #include <cstdio> #include <queue> #d

poj 3784(对顶堆)

Running Median Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 1824   Accepted: 889 Description For this problem, you will write a program that reads in a sequence of 32-bit signed integers. After each odd-indexed value is read, output t

P1168 中位数(对顶堆)

题意:维护一个序列,两种操作 1.插入一个数 2.输出中位数(若长度为偶数,输出中间两个较小的那个) 对顶堆 维护一个小根堆,一个大根堆,大根堆存1--mid,小根堆存mid+1---n 这样对顶必有中位数. 每次操作后维护两个堆元素数量,保证一个比另一个多1或相等 #include<cstdio> #include<iostream> #include<algorithm> #include<queue> using namespace std; #def

浅谈对顶堆

对顶堆详解 我们知道,堆是一种极有用的数据结构.它能在短时间内将数据维护成单调递增/递减的序列.但是这种"朴素堆"对于问题求解起到的效果毕竟是有限的.所以我们在朴素堆的基础上,进行深入思考和适当变形,使之能解决一些其他的用朴素堆解决不了的问题,并使思路变得简洁有效. 这篇随笔就堆中的一个分支--对顶堆进行讲解,读者在阅读前应该掌握堆的基本概念,以便于更好地理解对顶堆. 如果把堆中的大根堆想成一个上宽下窄的三角形,把小根堆想成一个上窄下宽的三角形,那么对顶堆就可以具体地被想象成一个&qu

Running Median POJ - 3784 (对顶堆/优先队列)

For this problem, you will write a program that reads in a sequence of 32-bit signed integers. After each odd-indexed value is read, output the median (middle value) of the elements received so far. Input The first line of input contains a single int

10/16 对顶堆算法研究(POJ 3784)

/* 考虑维护两个堆 一个堆是大根堆,存储1-x的元素 一个堆是小根堆,存储x+1-N的元素 对于一个加入的元素y,考虑将其加入大根堆or小根堆? 如果y>mid,那么将其加入小根堆(上面的堆) 如果y<mid,那么将其加入大根堆(下面的堆) 并且在每一次操作之后维护堆的状态是合法的! 也就是维护堆得大小正确 */#include<cstdio>#include<algorithm>#include<cstring>#include<queue>

中位数 对顶堆

题目描述 给出一个长度为NNN的非负整数序列AiA_iAi?,对于所有1≤k≤(N+1)/21 ≤ k ≤ (N + 1) / 21≤k≤(N+1)/2,输出A1,A3,-,A2k?1A_1, A_3, -, A_{2k - 1}A1?,A3?,-,A2k?1?的中位数.即前1,3,5,-1,3,5,-1,3,5,-个数的中位数. 输入输出格式 输入格式: 第111行为一个正整数NNN,表示了序列长度. 第222行包含NNN个非负整数Ai(Ai≤109)A_i (A_i ≤ 10^9)Ai?(A

P1801 黑匣子[堆]

题目描述 Black Box是一种原始的数据库.它可以储存一个整数数组,还有一个特别的变量i.最开始的时候Black Box是空的.而i等于0.这个Black Box要处理一串命令. 命令只有两种: ADD(x):把x元素放进BlackBox; GET:i加1,然后输出Blackhox中第i小的数. 记住:第i小的数,就是Black Box里的数的按从小到大的顺序排序后的第i个元素.例如: 我们来演示一下一个有11个命令的命令串.(如下图所示) 现在要求找出对于给定的命令串的最好的处理方法.AD

poj 3784 用堆动态求解中位数

堆真是一种简单而又神奇的数据结构,以前用它求过前kth的数,现在又可以用两个堆来动态求解中位数. 算法: 构建一个大顶堆和一个小顶堆,分别记为g和l. 假设当前中位数为mid,新读入一个数为tmp,则: 1.如果tmp < mid,则将tmp插入大顶堆,跳到步骤3. 2.如果tmp >= mid,则将tmp插入小顶堆,跳到步骤4. 3.如果大顶堆的元素个数比小顶堆多2(两个堆个数不平衡),则将mid插入小顶堆,弹出大顶堆堆顶元素为新的mid. 4.与步骤3相反,如果小顶堆的元素个数比大顶堆多2