洛谷 题解 P3871 【[TJOI2010]中位数】
这题先定义一个大根堆(maxn)维护mid(n为奇数mid+1)的元素。再定义一个小根堆(minn)维护mid(n为奇数mid+1)到n的元素。然后对于插入元素的情况进行分类讨论。
当add x时
一.n 是奇数
1.从大根堆中取出元素y并弹出。
2.大根堆中插入元素min(x,y)。
3.小根堆中插入元素max(x,y)。
二.n 是偶数
1.从小根堆中取出元素y并弹出。
2.大根堆中插入元素min(x,y)。
3.小根堆中插入元素max(x,y)。
当询问时输出大根堆中的堆顶元素即可。
addmax(大根堆中元素个数) addmin(小根堆中元素个数) maxn(大根堆) minn(小根堆)
堆的操作(以大根堆为例)
1.堆的元素下调
void shiftdownmax(int x){
int t,flag=0;
while(x*2<=addmax&&flag==0){
if(maxn[x]<maxn[x*2])t=x*2;
else t=x;
if(x*2+1<=addmax){
if(maxn[t]<maxn[x*2+1])t=x*2+1;
}
if(t!=x){
swap(maxn[t],maxn[x]);
x=t;
}else flag=1;
}
}
2.堆的元素上调
void shiftdownmax(int x){
int t,flag=0;
while(x*2<=addmax&&flag==0){
if(maxn[x]<maxn[x*2])t=x*2;
else t=x;
if(x*2+1<=addmax){
if(maxn[t]<maxn[x*2+1])t=x*2+1;
}
if(t!=x){
swap(maxn[t],maxn[x]);
x=t;
}else flag=1;
}
}
3.建堆
由于堆的性质,只要调整一半的元素即可。
for(int i=1;i<=tmp;++i){
addmax++;
maxn[addmax]=a[i];
}
for(int i=addmax/2;i>=1;--i){
shiftdownmax(i);
}
4.取出元素
取出第一个元素将最后一个元素放在第一个元素的位置,并且元素个数减1,对堆顶进行下调操作。
int y=maxn[1];
maxn[1]=maxn[addmax--];
shiftdownmax(1);
5.加入元素
在堆尾加入新元素并且对其进行上调操作
maxn[++addmax]=min(x,y);
shiftupmax(addmax);
ac代码
#include<bits/stdc++.h>
using namespace std;
int n,m,x,addmax,addmin,a[100010],maxn[60010],minn[60010];
char str[5];
void shiftdownmax(int x){//大根堆向下调整
int t,flag=0;
while(x*2<=addmax&&flag==0){
if(maxn[x]<maxn[x*2])t=x*2;
else t=x;
if(x*2+1<=addmax){
if(maxn[t]<maxn[x*2+1])t=x*2+1;
}
if(t!=x){
swap(maxn[t],maxn[x]);
x=t;
}else flag=1;
}
}
void shiftdownmin(int x){//小根堆向下调整
int t,flag=0;
while(x*2<=addmin&&flag==0){
if(minn[x]>minn[x*2])t=x*2;
else t=x;
if(x*2+1<=addmin){
if(minn[t]>minn[x*2+1])t=x*2+1;
}
if(t!=x){
swap(minn[t],minn[x]);
x=t;
}else flag=1;
}
}
void shiftupmax(int x) {//大根堆向上调整
int flag=0;
if(x==1) return;
while(x!=1&&flag==0){
if(maxn[x]>maxn[x/2]) swap(maxn[x],maxn[x/2]);
else flag=1;
x=x/2;
}
}
void shiftupmin(int x) {//小根堆向上调整
int flag=0;
if(x==1) return;
while(x!=1 && flag==0){
if(minn[x]<minn[x/2]) swap(minn[x],minn[x/2]);
else flag=1;
x=x/2;
}
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;++i){
scanf("%d",&a[i]);
}
addmax=0;
addmin=0;
sort(a+1,a+1+n);
if(n==1) maxn[++addmax]=a[1];//考虑特殊情况
else{
int tmp=n/2;
if(n%2) tmp++;
for(int i=1;i<=tmp;++i){
addmax++;
maxn[addmax]=a[i];
}
for(int i=addmax/2;i>=1;--i){
shiftdownmax(i);
}
for(int i=tmp+1;i<=n;++i){
addmin++;
minn[addmin]=a[i];
}
for(int i=addmin/2;i>=1;--i){
shiftdownmin(i);
}
}
scanf("%d",&m);
while(m--){
scanf("%s",str);
if(str[0]=='m'){
printf("%d\n",maxn[1]);
}
else{
scanf("%d",&x);
if(n%2){
int y=maxn[1];
maxn[1]=maxn[addmax--];
shiftdownmax(1);
maxn[++addmax]=min(x,y);
shiftupmax(addmax);
minn[++addmin]=max(x,y);
shiftupmin(addmin);
n++;//记得更新n
}
else{
int y=minn[1];
minn[1]=minn[addmin--];
shiftdownmin(1);
minn[++addmin]=max(x,y);
shiftupmin(addmin);
maxn[++addmax]=min(x,y);
shiftupmax(addmax);
n++;
}
}
}
return 0;
}
洛谷 题解 P3871 【[TJOI2010]中位数】的更多相关文章
- 洛谷 P3871 [TJOI2010]中位数 解题报告
P3871 [TJOI2010]中位数 题目描述 给定一个由N个元素组成的整数序列,现在有两种操作: 1 add a 在该序列的最后添加一个整数a,组成长度为N + 1的整数序列 2 mid 输出当前 ...
- 洛谷——P3871 [TJOI2010]中位数
P3871 [TJOI2010]中位数 一眼秒掉,这不是splay水题吗,套模板 #include<bits/stdc++.h> #define IL inline #define N 1 ...
- 洛谷 题解 UVA572 【油田 Oil Deposits】
这是我在洛谷上的第一篇题解!!!!!!!! 这个其实很简单的 我是一只卡在了结束条件这里所以一直听取WA声一片,详细解释代码里见 #include<iostream> #include&l ...
- 洛谷 题解 P1600 【天天爱跑步】 (NOIP2016)
必须得说,这是一道难题(尤其对于我这样普及组205分的蒟蒻) 提交结果(NOIP2016 天天爱跑步): OJ名 编号 题目 状态 分数 总时间 内存 代码 / 答案文件 提交者 提交时间 Libre ...
- 洛谷题解P4314CPU监控--线段树
题目链接 https://www.luogu.org/problemnew/show/P4314 https://www.lydsy.com/JudgeOnline/problem.php?id=30 ...
- 洛谷P3871 [TJOI2010]中位数(splay)
题目描述 给定一个由N个元素组成的整数序列,现在有两种操作: 1 add a 在该序列的最后添加一个整数a,组成长度为N + 1的整数序列 2 mid 输出当前序列的中位数 中位数是指将一个序列按照从 ...
- 【题解】Luogu P3871 [TJOI2010]中位数
平衡树板题 原题传送门 这道题要用Splay,我博客里有对Splay的详细介绍 每次加入一个数,把数插入平衡树中 并且要记录一共有多少个数 每次查询就查询平衡树中第(总数-1)/2+1个数 十分暴力 ...
- 洛谷题解 CF777A 【Shell Game】
同步题解 题目翻译(可能有童鞋没读懂题面上的翻译) 给你三张牌0,1,2. 最初选一张,然后依次进行n次交换,交换规则为:中间一张和左边的一张,中间一张和右边一张,中间一张和左边一张...... 最后 ...
- 洛谷题解 CF807A 【Is it rated?】
同步题解 题目 好吧,来说说思路: 1.先读入啦~(≧▽≦)/~啦啦啦 2.判断a[i]赛前赛后是否同分数,如果分数不同,则输出,return 0 . 3.如果同分数,则判断a[i]赛前(或赛后)是否 ...
随机推荐
- 进军pc市场 华为剑走偏锋可有戏?
尽管官方并未正式公布,但在前段时间,华为将要进军PC市场的消息在业内传得沸沸扬扬,据知情人士曝料,其第一款个人电脑将在今年4月上线.而华为将进军PC市场的消息,对其他智能手机厂商来说又意味着什么呢? ...
- PythonDay04
## 第四章 ### 今日内容 - 列表- 元组- range ### 列表 列表相比于字符串,不仅可以储存不同的数据类型,而且可以储存大量数据,是一种可变的数据类型 64位python的限制是 11 ...
- virtualbox安装ubuntu16 LTS及其配置
一.下载安装VirtualBox 1. 从官网下载VirtualBox,目前版本:VirtualBox 6.0.6 for Windows hosts x86/amd64 2. 下载好之后安装Virt ...
- 假装前端工程师(一)Icework + GitHub pages 快速构建可自定义迭代开发的 react 网站
icework + gh-pages 超快部署超多模版页面 项目地址:https://github.com/yhyddr/landingpage效果地址:https://yhyddr.github.i ...
- ASP.NET Core MVC 之依赖注入 Controller
ASP.NET Core MVC 控制器应通过构造函数明确地请求它们地依赖关系,在某些情况下,单个控制器地操作可能需要一个服务,在控制器级别上的请求可能没有意义.在这种情况下,也可以将服务作为 Ac ...
- rwcheck:为嵌入式设备设计的读写压测工具
我设计的一款读写压测工具,开源在我的github仓库 rwcheck是一个对嵌入式设备进行读写压测的工具 什么是rwcheck 正如其名,rwcheck工具用于读写压测.它是什么工作原理呢?为什么要用 ...
- 聊聊我在这家公司设计的SSO
最近小明遇到一个需求:需要将几个独立的系统(子系统)汇总到一个集中的系统(父系统)当中,当用户在父系统登录过后,再点击这几个子系统,就可以免登录跳转到任意一个系统.当时一听,duang~duang~就 ...
- Linux源码包安装apache(httpd)
我这里实验是用的CentOS7 #事先先检查一下自己的linux是否安装apache [root@localhost ~]#rpm –q httpd #如果已安装则先卸载原来的apache [root ...
- SpringMVC源码分析4:DispatcherServlet如何找到正确的Controller
SpringMVC是目前主流的Web MVC框架之一. 我们使用浏览器通过地址 http://ip:port/contextPath/path进行访问,SpringMVC是如何得知用户到底是访问哪个 ...
- Oracle 12c Adoption Discussion — Summary
Morning (@9:30) Oracle 12c Overview & Features for Developers Oracle Database In-Memory Deep Div ...