这题先定义一个大根堆(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]中位数】的更多相关文章

  1. 洛谷 P3871 [TJOI2010]中位数 解题报告

    P3871 [TJOI2010]中位数 题目描述 给定一个由N个元素组成的整数序列,现在有两种操作: 1 add a 在该序列的最后添加一个整数a,组成长度为N + 1的整数序列 2 mid 输出当前 ...

  2. 洛谷——P3871 [TJOI2010]中位数

    P3871 [TJOI2010]中位数 一眼秒掉,这不是splay水题吗,套模板 #include<bits/stdc++.h> #define IL inline #define N 1 ...

  3. 洛谷 题解 UVA572 【油田 Oil Deposits】

    这是我在洛谷上的第一篇题解!!!!!!!! 这个其实很简单的 我是一只卡在了结束条件这里所以一直听取WA声一片,详细解释代码里见 #include<iostream> #include&l ...

  4. 洛谷 题解 P1600 【天天爱跑步】 (NOIP2016)

    必须得说,这是一道难题(尤其对于我这样普及组205分的蒟蒻) 提交结果(NOIP2016 天天爱跑步): OJ名 编号 题目 状态 分数 总时间 内存 代码 / 答案文件 提交者 提交时间 Libre ...

  5. 洛谷题解P4314CPU监控--线段树

    题目链接 https://www.luogu.org/problemnew/show/P4314 https://www.lydsy.com/JudgeOnline/problem.php?id=30 ...

  6. 洛谷P3871 [TJOI2010]中位数(splay)

    题目描述 给定一个由N个元素组成的整数序列,现在有两种操作: 1 add a 在该序列的最后添加一个整数a,组成长度为N + 1的整数序列 2 mid 输出当前序列的中位数 中位数是指将一个序列按照从 ...

  7. 【题解】Luogu P3871 [TJOI2010]中位数

    平衡树板题 原题传送门 这道题要用Splay,我博客里有对Splay的详细介绍 每次加入一个数,把数插入平衡树中 并且要记录一共有多少个数 每次查询就查询平衡树中第(总数-1)/2+1个数 十分暴力 ...

  8. 洛谷题解 CF777A 【Shell Game】

    同步题解 题目翻译(可能有童鞋没读懂题面上的翻译) 给你三张牌0,1,2. 最初选一张,然后依次进行n次交换,交换规则为:中间一张和左边的一张,中间一张和右边一张,中间一张和左边一张...... 最后 ...

  9. 洛谷题解 CF807A 【Is it rated?】

    同步题解 题目 好吧,来说说思路: 1.先读入啦~(≧▽≦)/~啦啦啦 2.判断a[i]赛前赛后是否同分数,如果分数不同,则输出,return 0 . 3.如果同分数,则判断a[i]赛前(或赛后)是否 ...

随机推荐

  1. C#开发可播放摄像头及任意格式视频的播放器

    前言 本文主要讲述,在WPF中,借助Vlc.DotNet调用VLC类库,实现视频播功能,下面我们先来做开发前的准备工作. 准备工作 首先,我们创建一个项目WpfVLC,然后,进入Neget搜索Vlc. ...

  2. java高并发系列 - 第23天:JUC中原子类,一篇就够了

    这是java高并发系列第23篇文章,环境:jdk1.8. 本文主要内容 JUC中的原子类介绍 介绍基本类型原子类 介绍数组类型原子类 介绍引用类型原子类 介绍对象属性修改相关原子类 预备知识 JUC中 ...

  3. 【Java例题】8.2 手工编写字符串统计的可视化程序

      2. 手工编写字符串统计的可视化程序. 一个Frame窗体容器,布局为null,两个TextField组件,一个Button组件. Button组件上添加ActionEvent事件监听器Actio ...

  4. 统一流控服务开源:基于.Net Core的流控服务

    先前有一篇博文,梳理了流控服务的场景.业界做法和常用算法 统一流控服务开源-1:场景&业界做法&算法篇 最近完成了流控服务的开发,并在生产系统进行了大半年的验证,稳定可靠.今天整理一下 ...

  5. 史上最全面的SignalR系列教程-2、SignalR 实现推送功能-永久连接类实现方式

    1.概述 通过上篇史上最全面的SignalR系列教程-1.认识SignalR文章的介绍,我们对SignalR技术已经有了一个全面的了解.本篇开始就通过SignalR的典型应用的实现方式做介绍,例子虽然 ...

  6. javaweb基础整理随笔-----上传与下载步骤详解

    这次整理的是上传与下载的原生代码解析: 上传:1.对页面的要求:enctype="multipart/form-data" method="post"      ...

  7. ImageLoader_显示图片

    public class MainActivity extends AppCompatActivity { private ListView lv; private List<Bean.Resu ...

  8. 章节十六、3-TestNG方法和类注解

    一.Test Suite(测试套件) 我们通常认为一个testcase就是一个测试方法,但是会有很多的testcase,所以我们不可能把所有的testcase放到同一个测试类中,假如需要测试的页面有1 ...

  9. linux+jenkins+python+svn 自动化测试集成之路

    本文背景: 背景1---个人基础: 本机win7上安装pycharm,使用python搭建API自动化测试框架,本地运行Pass.本机上搭建jenkins,创建测试任务,定时构建Pass. 背景2-- ...

  10. 后端开发实践系列之三——事件驱动架构(EDA)编码实践

    在本系列的前两篇文章中,笔者分别讲到了后端项目的代码模板和DDD编码实践,在本文中,我将继续以编码实践的方式分享如何落地事件驱动架构. 单纯地讲事件驱动架构(Event Driven Architec ...