【bzoj4552】【Tjoi2016&Heoi2016】【NOIP2016模拟7.12】排序
题目
在2016年,佳媛姐姐喜欢上了数字序列。因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他。这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排序分为两种:1:(0,l,r)表示将区间[l,r]的数字升序排序2:(1,l,r)表示将区间[l,r]的数字降序排序最后询问第q 位置上的数字。
分析
二分答案,
把二分出的ans与原序列比较,小于ans的数改为-1,大于ans的数改为1。
对于输入的每一个修改,用线段树来处理。
最后求出\(q\)位上的数是-1还是1,然后接着二分。
#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const int maxlongint=2147483647;
const int mo=1000000007;
const int N=100005;
using namespace std;
int a[N],n,m,re[N][4],k,ans,lazy[N*5],_0[N*5],_1[N*5];
int down(int v,int mid,int l,int r)
{
	if(lazy[v]==-1)
	{
		lazy[v*2+1]=lazy[v*2]=lazy[v];
		_0[v*2]=mid-l+1;
		_0[v*2+1]=r-(mid+1)+1;
		_1[v*2]=0;
		_1[v*2+1]=0;
	}
	if(lazy[v]==1)
	{
		lazy[v*2+1]=lazy[v*2]=lazy[v];
		_1[v*2]=mid-l+1;
		_1[v*2+1]=r-(mid+1)+1;
		_0[v*2]=0;
		_0[v*2+1]=0;
	}
	lazy[v]=0;
}
int put(int v,int l,int r,int x,int y)
{
	if(l==r)
	{
		if(y==-1)
			_0[v]=1;
				else _1[v]=1;
		return 0;
	}
	int mid=(l+r)/2;
	if(x<=mid)
		put(v*2,l,mid,x,y);
	else
		put(v*2+1,mid+1,r,x,y);
	_0[v]=_0[v*2]+_0[v*2+1];
	_1[v]=_1[v*2]+_1[v*2+1];
}
int get(int v,int l,int r,int x,int y)
{
	if(l==x && r==y)
	{
		return _1[v];
	}
	int mid=(l+r)/2;
	down(v,mid,l,r);
	int o;
	if(y<=mid)
		o=get(v*2,l,mid,x,y);
	else
	if(x>mid)
		o=get(v*2+1,mid+1,r,x,y);
	else
		o=get(v*2,l,mid,x,mid)+get(v*2+1,mid+1,r,mid+1,y);
	_0[v]=_0[v*2]+_0[v*2+1];
	_1[v]=_1[v*2]+_1[v*2+1];
	return o;
}
int change(int v,int l,int r,int x,int y,int value)
{
	if(y<x) return 0;
	int mid=(l+r)/2;
	if(l==x && r==y)
	{
		lazy[v]=value;
		if(value<0)
		{
			_0[v]=r-l+1;
			_1[v]=0;
		}
		else
		{
			_1[v]=r-l+1;
			_0[v]=0;
		}
		return 0;
	}
	down(v,mid,l,r);
	if(y<=mid)
		change(v*2,l,mid,x,y,value);
	else
	if(x>mid)
		change(v*2+1,mid+1,r,x,y,value);
	else
		change(v*2,l,mid,x,mid,value),change(v*2+1,mid+1,r,mid+1,y,value);
	_0[v]=_0[v*2]+_0[v*2+1];
	_1[v]=_1[v*2]+_1[v*2+1];
}
int find(int v,int l,int r,int x)
{
	if(l==r)
	{
		return _0[v];
	}
	int mid=(l+r)/2;
	down(v,mid,l,r);
	int o;
	if(x<=mid)
		o=find(v*2,l,mid,x);
	else
		o=find(v*2+1,mid+1,r,x);
	_0[v]=_0[v*2]+_0[v*2+1];
	_1[v]=_1[v*2]+_1[v*2+1];
	return o;
}
bool check(int x)
{
	memset(lazy,0,sizeof(lazy));
	memset(_0,0,sizeof(_0));
	memset(_1,0,sizeof(_1));
	for(int i=1;i<=n;i++)
	{
		int g=a[i]<=x?-1:1;
		put(1,1,n,i,g);
	}
	for(int i=1;i<=m;i++)
	{
		int p1=get(1,1,n,re[i][2],re[i][3]);
		if(!re[i][1])
		{
			change(1,1,n,re[i][2],re[i][3]-p1,-1);
			change(1,1,n,re[i][3]-p1+1,re[i][3],1);
		}
		else
		{
			change(1,1,n,re[i][2],re[i][2]+p1-1,1);
			change(1,1,n,re[i][2]+p1,re[i][3],-1);
		}
	}
	if(find(1,1,n,k))
		return true;
			else return false;
}
int main()
{
	scanf("%d%d",&n,&m);
	for(int i=1;i<=n;i++)
	{
		scanf("%d",&a[i]);
	}
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&re[i][1],&re[i][2],&re[i][3]);
	}
	scanf("%d",&k);
	int l=1,r=n;
	while(l<r)
	{
		int mid=(l+r)/2;
		if(check(mid))
		{
			r=mid;
		}
		else
		{
			l=mid+1;
		}
	}
	printf("%d",l);
}
												
											【bzoj4552】【Tjoi2016&Heoi2016】【NOIP2016模拟7.12】排序的更多相关文章
- bzoj千题计划128:bzoj4552: [Tjoi2016&Heoi2016]排序
		
http://www.lydsy.com/JudgeOnline/problem.php?id=4552 二分答案 把>=mid 的数看做1,<mid 的数看做0 这样升序.降序排列相当于 ...
 - 【bzoj 4554】【Tjoi2016&Heoi2016】【NOIP2016模拟7.12】游戏
		
题目 分析 当没有石头的时候,就用二分图匹配来做. 但现在加入了石头, 所以,求出每行和每列联通快的个数,如果有一块平地,包括在某个行联通块以及某个列联通块中,连边. //无聊打了网络流,匈牙利也可以 ...
 - [BZOJ4552][TJOI2016&&HEOI2016]排序(二分答案+线段树/线段树分裂与合并)
		
解法一:二分答案+线段树 首先我们知道,对于一个01序列排序,用线段树维护的话可以做到单次排序复杂度仅为log级别. 这道题只有一个询问,所以离线没有意义,而一个询问让我们很自然的想到二分答案.先二分 ...
 - BZOJ4552 [Tjoi2016&Heoi2016]排序  【二分 + 线段树】
		
题目链接 BZOJ4552 题解 之前去雅礼培训做过一道题,\(O(nlogn)\)维护区间排序并能在线查询 可惜我至今不能get 但这道题有着\(O(nlog^2n)\)的离线算法 我们看到询问只有 ...
 - [bzoj4552][Tjoi2016][Heoi2016]排序
		
Description 给出一个$1$到$n$的全排列,现在对这个全排列序列进行$m$次局部排序,排序分为$2$种: $1.(0,l,r)$表示将区间$[l,r]$的数字升序排序; $2.(1,l,r ...
 - BZOJ4552: [Tjoi2016&Heoi2016]排序
		
Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题 ,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这 ...
 - [bzoj4552][Tjoi2016&Heoi2016]排序-二分+线段树
		
Brief Description DZY有一个数列a[1..n],它是1∼n这n个正整数的一个排列. 现在他想支持两种操作: 0, l, r: 将a[l..r]原地升序排序. 1, l, r: 将a ...
 - BZOJ4552:[TJOI2016&HEOI2016]排序(线段树,二分)
		
Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他. 这个难题是这样子的:给出一个1到n的全排列,现在对这 ...
 - 2018.08.01 BZOJ4552: [Tjoi2016&Heoi2016]排序(二分+线段树)
		
传送门 线段树简单题. 二分答案+线段树排序. 实际上就是二分答案mid" role="presentation" style="position: relat ...
 
随机推荐
- Visual Studio Code 断点调试Nodejs程序跳过node内部模块(internal modules)
			
Built-in core modules of Node.js can be referred to by the ‘magic name’ <node_internals> in a ...
 - 阶段3 1.Mybatis_03.自定义Mybatis框架_3.自定义mybatis的编码-根据测试类中缺少的创建接口和类
			
先认识一下这几个类.Resources是一个class SqlSessionFactoryBuilder 创建新项目 复制相关的依赖 复制之前的代码 复制到当前项目的src下 把Mybits的依赖删除 ...
 - add_prefix()函数
			
对于series,是给索引列加前缀. 对于Dataframe,是给列名加前缀. 参考:https://www.cjavapy.com/article/276/
 - 使用docker compose 构建多个镜像
			
定义docker compose version: ' services: composedb: image: mysql/mysql-server container_name: composedb ...
 - 深入理解java:2.1. volatile的使用及其原理
			
引言 在多线程并发编程中synchronized和Volatile都扮演着重要的角色,Volatile是轻量级的synchronized,它在多处理器开发中保证了共享变量的“可见性”. 可见性的意思是 ...
 - CentOS7搭建NTP服务器及客户端同步时间
			
一.服务器配置 1.查看服务器.客户端操作系统版本 [root@hadoop101 ~]# cat /etc/redhat-release CentOS Linux release (Core) 2. ...
 - java学习day1
			
一.常用的DOS命令 1.打开cmd 窗口键+r --> 输入cmd --> 确认 2.常用的dos命令 dir:列出当前目录下的所有文件及文件夹 md:创建一个新的目录 rd:删除目录 ...
 - swtich和case语句中,定义变量要加花括号
			
转自: http://blog.chinaunix.net/uid-27103408-id-3340702.html http://www.xuebuyuan.com/2070170.html swi ...
 - django商城项目之用sentry管理日志
			
之前写商城项目的时候,采用的日志处理方式为在终端输出或者写入文件,这样的话,项目部署上线之后,若服务器出现错误,需要到服务器查看相关的错误日志,很不方便.后期在学习别人开源项目的时候,学习到一个开源的 ...
 - 为ASP.NET按钮(Button)添加确认对话框
			
http://www.cnblogs.com/blodfox777/articles/1261303.html Button有两个点击事件: onclick 触发服务端事件,脚本为c#或VB.NET ...