洛谷 题解 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]赛前(或赛后)是否 ... 
随机推荐
- 对JAVA Bean使用PropertyDescriptor反射调用JAVA方法低耦合
			对于符合JAVA Bean规范的bean,调用其方法应优先使用java.beans.PropertyDescriptor获取Method进行方法调用,以获得更大的可维护性. public void g ... 
- 认识 tomcat 被占用问题
			(1) Server 中的 port 该端口为tomcat使用jvm的端口,必须保证唯一性,否则tomcat启动不成功: (2) Connector 中的 port 该端口为tomcat中所有web应 ... 
- RabbitMQ与spring集成,配置完整的生产者和消费者
			RabbitMQ与AMQP协议详解可以看看这个 http://www.cnblogs.com/frankyou/p/5283539.html 下面是rabbitMQ和spring集成的配置,我配置了二 ... 
- elasticsearch启动错误整理
			一.elasticsearch错误复现 (一).环境 配置环境 OS:CentOS 7.4 64bit elasticsearch版本: - ip:10.18.43.170 java版本:java - ... 
- Hyper-v设置linux固定ip
			一.创建CentOS 7专用的虚拟交换机 打开Hyper-v控制面板,找到右边的“虚拟交换机管理器” 进去后,点击“新建虚拟网络交换机”,填写名称后,选择“内部” 打开网络中心,修改配置如下图,注意i ... 
- js拖拽上传图片
			有时候,在开发中,需要遇到拖拽上传图片的需求,即从磁盘选中一张或多张图片,然后按着鼠标把图片拖动到页面上指定的区域,实现图片的上传. 1.后端上传图片的接口 我是之前用vue写一个简单的后台系统的时候 ... 
- laravel新项目报错 No application encryption key has been specified.
			解决办法, 若文件根目录下没有 .env 1..env.example 改名使用命令 copy 修改为 .env 2.使用命令 php artisan key:generate 获取密码,自动保存到 ... 
- js常见兼容性问题以及解决方法
			1.关于使用 event对象,出现的兼容性问题IE/Chrom: event.clientX;event.clientYFF/IE9以上/Chrom: 传参e e.clientX;e.client ... 
- Python3基本数据类型之列表
			1.初识列表 列表(List)是Python3中的"容器型"数据类型. 列表通过中括号把一堆数据括起来的方式形成,列表的长度不限. 列表里面的元素可以是不同的数据类型,但是一般是相 ... 
- ajax方法请求成功后,没有执行success的方法
			$.ajax( { type: "POST", url: "AddSupplier.aspx", dataType:"text", data ... 
