题目

在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】排序的更多相关文章

  1. bzoj千题计划128:bzoj4552: [Tjoi2016&Heoi2016]排序

    http://www.lydsy.com/JudgeOnline/problem.php?id=4552 二分答案 把>=mid 的数看做1,<mid 的数看做0 这样升序.降序排列相当于 ...

  2. 【bzoj 4554】【Tjoi2016&Heoi2016】【NOIP2016模拟7.12】游戏

    题目 分析 当没有石头的时候,就用二分图匹配来做. 但现在加入了石头, 所以,求出每行和每列联通快的个数,如果有一块平地,包括在某个行联通块以及某个列联通块中,连边. //无聊打了网络流,匈牙利也可以 ...

  3. [BZOJ4552][TJOI2016&&HEOI2016]排序(二分答案+线段树/线段树分裂与合并)

    解法一:二分答案+线段树 首先我们知道,对于一个01序列排序,用线段树维护的话可以做到单次排序复杂度仅为log级别. 这道题只有一个询问,所以离线没有意义,而一个询问让我们很自然的想到二分答案.先二分 ...

  4. BZOJ4552 [Tjoi2016&Heoi2016]排序 【二分 + 线段树】

    题目链接 BZOJ4552 题解 之前去雅礼培训做过一道题,\(O(nlogn)\)维护区间排序并能在线查询 可惜我至今不能get 但这道题有着\(O(nlog^2n)\)的离线算法 我们看到询问只有 ...

  5. [bzoj4552][Tjoi2016][Heoi2016]排序

    Description 给出一个$1$到$n$的全排列,现在对这个全排列序列进行$m$次局部排序,排序分为$2$种: $1.(0,l,r)$表示将区间$[l,r]$的数字升序排序; $2.(1,l,r ...

  6. BZOJ4552: [Tjoi2016&Heoi2016]排序

    Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题 ,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这 ...

  7. [bzoj4552][Tjoi2016&Heoi2016]排序-二分+线段树

    Brief Description DZY有一个数列a[1..n],它是1∼n这n个正整数的一个排列. 现在他想支持两种操作: 0, l, r: 将a[l..r]原地升序排序. 1, l, r: 将a ...

  8. BZOJ4552:[TJOI2016&HEOI2016]排序(线段树,二分)

    Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他. 这个难题是这样子的:给出一个1到n的全排列,现在对这 ...

  9. 2018.08.01 BZOJ4552: [Tjoi2016&Heoi2016]排序(二分+线段树)

    传送门 线段树简单题. 二分答案+线段树排序. 实际上就是二分答案mid" role="presentation" style="position: relat ...

随机推荐

  1. lua源码学习篇三:赋值表达式解析的流程

    上节说到表达式的解析问题,exprstate函数用于解析普通的赋值表达式.lua语言支持多变量赋值.本文先从单变量赋值表达式讲起. a = b = c = a + b 对于简单的两个数的求和过程,lu ...

  2. Jmeter之简单控制器

    在很多情况下,我们 需要将多个请求放置在一起,但是没有逻辑上的操作,这个时候就可以使用简单控制器了. 如 :

  3. finereport连接mysql8.0的解决办法

    1.具体连接操作 首先将mysql-connector-java-8.0以上的jar包放到FindReport安装目录下的webapps下的WEB-INF下的lib下. 打开finereport,找到 ...

  4. 学了一天的golang从入门到放弃

    Google的go就是个二货,不实用,它最多只能和c比简单.low!

  5. 【Qt开发】Qt5.7中文显示乱码解决方法两种

    升级到Qt5.X之后,原先解决的Qt显示中文乱码的方法突然不适用了,找了很多方式来解决这个问题 第一种: 在公司代码里看到的方法,先将对应的cpp文件用windows自带的记事本打开,另存为UTF-8 ...

  6. python下对mysql数据库的链接操作

    参考网址: https://blog.csdn.net/guofeng93/article/details/53994112 https://blog.csdn.net/Chen_Eris/artic ...

  7. 命令行模式和Python交互模式的区别

    1.命令行模式: 在Windows开始菜单选择“命令提示符”,就进入到命令行模式,它的提示符类似C:\Users\>: 2.python交互模式 在命令行模式下敲命令python,就看到类似如下 ...

  8. KMP字符串匹配 模板 洛谷 P3375

    KMP字符串匹配 模板 洛谷 P3375 题意 如题,给出两个字符串s1和s2,其中s2为s1的子串,求出s2在s1中所有出现的位置. 为了减少骗分的情况,接下来还要输出子串的前缀数组next.(如果 ...

  9. uboot初识

    一. 什么是uboot 1.1. uboot的由来 1.1.1. uboot是SourceForge上的开源项目 1.1.2. uboot就是由一个人发起,然后由整个网络上所有感兴趣的人共同维护发展而 ...

  10. object in javascript

    枚举对象属性 for....in 列举obj的可枚举属性,包括自身和原型链上的 object.keys() 只列举对象本身的可枚举属性 创建对象的几种方式 对象字面量 const pre='test' ...