【Luogu P1168】【Luogu P1801&UVA 501】中位数&黑匣子(Black Box)——对顶堆相关
Luogu P1168
Luogu P1801
UVA 501(洛谷Remote Judge)
前置知识:堆、优先队列STL的使用
对顶堆
是一种在线维护第\(k\)小的算法。
其实就是开两个堆,一个是大根堆,一个是小根堆。两个堆的根相对。
下面借助题目P1168进行详细分析。
P1168
题意很好理解,不多作分析。
显然当\(i=1\)时,中位数就是\(a[1]\),记为\(mid\)。
我们可以使用对顶堆,把比\(mid\)小的存入大根堆,比mid大的存入小根堆。
当我们已经加入奇数个元素时,可以根据两个堆的大小调整\(mid\)值
- 当\(heap-big.size==heap-little.size\),当前\(mid\)即为中位数
- 当\(heap-big.size<heap-little.size\),将当前\(mid\)压入大根堆,小根堆的堆顶弹出并作为新的mid,重复以上过程直至\(heap-big.size==heap-little.size\)。
- 反之同理
那么这样不断操作就可以求出答案了。
#include<cstdio>
#include<queue>
using namespace std;
priority_queue<int> que1;//大根堆
priority_queue<int,vector<int>,greater<int>> que2;//小根堆
int n,a,mid;
int main()
{
scanf("%d",&n);
scanf("%d",&a);
mid=a;
printf("%d\n",a);
for (int i=2;i<=n;i++)
{
scanf("%d",&a);
if (a>mid) que2.push(a);
if (a<=mid) que1.push(a);
if (i%2==1)
{
if (que1.size()!=que2.size())
{
//不用while是因为两个堆的大小最多相差2。
if (que1.size()>que2.size())
{
que2.push(mid);
mid=que1.top();
que1.pop();
}
else
{
que1.push(mid);
mid=que2.top();
que2.pop();
}
}
printf("%d\n",mid);
}
}
return 0;
}
P1801&UVA 501
思路类似,不再重复
P1801
#include<queue>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
priority_queue<int,vector<int>,greater<int> > que2;
priority_queue<int,vector<int>,less<int> > que1;
int m,n,a[200005],T,u[200005];
int main()
{
//scanf("%d",&T);
T=1;
/*这是根据UVA 501修改的,两题其实是一样的,但是UVA 501有多组数据,且对输出格式
有要求*/
while (T--)
{
while (!que1.empty()) que1.pop();
while (!que2.empty()) que2.pop();
memset(a,0,sizeof(a));
memset(u,0,sizeof(u));
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",&u[i]);
int j=1,now=u[1];
for (int i=1;i<=m;i++)
{
if (que1.empty()) que1.push(a[i]);
else if (a[i]<que1.top()) que1.push(a[i]);
else que2.push(a[i]);
if (i==now)
{
while (i==now)
{
while (que1.size()<j)
{
que1.push(que2.top());
que2.pop();
}
while (que1.size()>j)
{
que2.push(que1.top());
que1.pop();
}
printf("%d\n",que1.top());
j++;
now=u[j];
if (j>n) return 0;
}
}
}
if (T) printf("\n");
}
return 0;
}
UVA 501
#include<queue>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
priority_queue<int,vector<int>,greater<int> > que2;
priority_queue<int,vector<int>,less<int> > que1;
int m,n,a[200005],T,u[200005];
int main()
{
scanf("%d",&T);
while (T--)
{
while (!que1.empty()) que1.pop();
while (!que2.empty()) que2.pop();
memset(a,0,sizeof(a));
memset(u,0,sizeof(u));
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",&u[i]);
int j=1,now=u[1];
for (int i=1;i<=m;i++)
{
if (que1.empty()) que1.push(a[i]);
else if (a[i]<que1.top()) que1.push(a[i]);
else que2.push(a[i]);
if (i==now)
{
while (i==now)
{
while (que1.size()<j)
{
que1.push(que2.top());
que2.pop();
}
while (que1.size()>j)
{
que2.push(que1.top());
que1.pop();
}
printf("%d\n",que1.top());
j++;
now=u[j];
if (j>n) break;
}
if (j>n) break;
}
if (j>n) break;
}
if (T) printf("\n");
}
return 0;
}
【Luogu P1168】【Luogu P1801&UVA 501】中位数&黑匣子(Black Box)——对顶堆相关的更多相关文章
- [luogu]P1168 中位数[堆]
[luogu]P1168 中位数 题目描述 给出一个长度为N的非负整数序列A[i],对于所有1 ≤ k ≤ (N + 1) / 2,输出A[1], A[3], …, A[2k - 1]的中位数.即前1 ...
- 洛谷 - P1801 - 黑匣子 - 对顶堆
这道题是提高+省选-的难度,做出来的话对数据结构题目的理解会增加很多. 可以使用一种叫做对顶堆的东西,对顶堆是在线维护第n小的logn的算法.大概的思路是,假如我们要找的是第n小,我们就维护一个大小为 ...
- P1168 中位数(对顶堆)
题意:维护一个序列,两种操作 1.插入一个数 2.输出中位数(若长度为偶数,输出中间两个较小的那个) 对顶堆 维护一个小根堆,一个大根堆,大根堆存1--mid,小根堆存mid+1---n 这样堆顶必有 ...
- luogu 3466 对顶堆
显然答案是将一段区间全部转化成了其中位数这样的话,需要维护一个数据结构支持查询当前所有数中位数对顶堆 用两个堆将 < 中位数的数放入大根堆将 > 中位数的数放入小根堆这样就会存在删除操作 ...
- P1801 黑匣子[对顶堆]
没错我就是专门找对顶堆练习题的.现在感觉对顶堆使用面有点狭窄.这道题由于我询问是随时间单调增的,而且数据比较友好,应该是插入几次就询问一下的.而中位数那题也是经常询问的.如果查询的东西不单调,或者查询 ...
- AcWing:106. 动态中位数(对顶堆)
依次读入一个整数序列,每当已经读入的整数个数为奇数时,输出已读入的整数构成的序列的中位数. 输入格式 第一行输入一个整数PP,代表后面数据集的个数,接下来若干行输入各个数据集. 每个数据集的第一行首先 ...
- LuoGu P1168 中位数
题目描述 给出一个长度为 $ N $ 的非负整数序列 $ A_i $ ,对于所有 $ 1 ≤ k ≤ (N + 1) / 2 $ ,输出 $ A_1, A_3, -, A_{2k - 1} $ 的中位 ...
- luogu P1168 中位数 |树状数组+二分
题目描述 给出一个长度为NN的非负整数序列A_i,对于所有1 ≤ k ≤ (N + 1) / 21≤k≤(N+1)/2,输出A_1, A_3, -, A_2k - 1的中位数.即前1,3,5,-个数的 ...
- 【Luogu P1048 Luogu P1016】采药/疯狂的采药
采药/疯狂的采药 两道模板题,分别是0-1背包和完全背包. 0-1背包 二维:dp[i][j]=max(dp[i-1][j-time[i]]+v[i],dp[i-1][j]); 由于i的状态由i-1的 ...
随机推荐
- bash_history文件怎么删除
Bash shell在“~/.bash_history”(“~/”表示用户目录)文件中保存了500条使用过的命令,这样可以使你输入使用过的长命令变得容易.每个在系统中拥有账号的用户在他的目录下都有一个 ...
- 设计模式(六)Prototype模式
Prototype模式就是不根据类来生成实例,而是根据实例来生成新实例.至于为什么不能根据类来生成实例,在最后会讲到. 还是根据实例程序来理解这种设计模式吧. 下面是实例代码. package Big ...
- Stringbuilder常用方法
一.创建Stringbuilder对象StringBuilder strB = new StringBuilder(); 1.append(String str)/append(Char c):字符串 ...
- SpringBoot系列:Spring Boot定时任务Spring Schedule
Spring Schedule是Spring提供的定时任务框架,相较于Quartz,Schedule更加简单易用,在中小型应用中,对于大部分需求,Schedule都可以胜任. 一.Spring Sch ...
- [模板]tarjan——最后通牒
这么久了我还是不会板子,你们随便笑话我吧. 再不会打我实在是无能为力了. 这篇博客写的像个智障一样...写它的目的就是自嘲? 才不是,为了方便查阅,因为我真的记不住. 对于割边,要存储该点入边的编号, ...
- CSPS模拟 100
我又挂分了T_T 这么吉利的数字..本来想考的好一点的 T1 没加当前弧优化(其实也不会),若志了 各种低错连篇而且没想到点不联通..没有奇度点就直接从1开始搜了 于是喜提70(犯了这两个若志错误应该 ...
- VIM编辑器的常用命令及使用!
在热门Linux操作系统中都会默认安装一款超好用的文本编辑器——名字叫“vim”,vim是vi编辑器的升级版. Vim能够得到这么多厂商与用户的认可,原因就是在Vim编辑器中有三种模式——命令模式.末 ...
- Python-webbrowser实现自动打开关、定时打开关闭网页/刷新网页
webbrowser- 方便的Web浏览器控制器,是Python一个模块,可实现自动打开关.定时打开关闭网页/刷新网页,在Unix下,图形浏览器在X11下更受欢迎,但如果图形浏览器不可用或X11显示器 ...
- Go 基础学习笔记 (5)| 数据类型说明与使用
在 Go 编程语言中,数据类型用于声明函数和变量. 数据类型的出现是为了把数据分成所需内存大小不同的数据,编程的时候需要用大数据的时候才需要申请大内存,就可以充分利用内存. Go 语言按类别有以下几种 ...
- [Bootstrap] Bootstrap学习笔记
1.因为bootstrap用到了html5的特性,为了正常使用,需要在最开头加上<!DOCTYPE html> 2.Bootstrap需要JQuery才能正常工作,所以需要导入jquery ...