Description

在2016年,佳媛姐姐喜欢上了数字序列。因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题
,需要你来帮助他。这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排
序分为两种:1:(0,l,r)表示将区间[l,r]的数字升序排序2:(1,l,r)表示将区间[l,r]的数字降序排序最后询问第q
位置上的数字。

Input

输入数据的第一行为两个整数n和m。n表示序列的长度,m表示局部排序的次数。1 <= n, m <= 10^5第二行为n个整
数,表示1到n的一个全排列。接下来输入m行,每一行有三个整数op, l, r, op为0代表升序排序,op为1代表降序
排序, l, r 表示排序的区间。最后输入一个整数q,q表示排序完之后询问的位置, 1 <= q <= n。1 <= n <= 10^5
,1 <= m <= 10^5
 

Output

输出数据仅有一行,一个整数,表示按照顺序将全部的部分排序结束后第q位置上的数字。

Sample Input

6 3
1 6 2 5 3 4
0 1 4
1 3 6
0 2 4
3

Sample Output

5
————————————————————————————————
二分p位置的值,把大于mid的数改为1,小于等于mid的数改为0,
变成01串后就可以用线段树实现排序了,像降序升序什么的操作就把1和0各堆到一边就可以辣
排序后如果p的位置上的数为0,说明答案比mid小,如果为1,说明答案比mid大。
至于为什么可以用二分呢
你想如果p位置上是1,说明mid较小,v[p]>mid,所以把v[p]给标记成了1。
如果p位置上是0,就是把v[p]<=mid,所以把v[p]标记成了0,
但是这样还有一些大于v[p]的位置也是0,所以继续往小的地方逼近答案。
满足单调所以就可以这么写辣
#include<cstdio>
#include<cstring>
#include<algorithm>
const int M=5e5+;
int read(){
int ans=,f=,c=getchar();
while(c<''||c>''){if(c=='-') f=-; c=getchar();}
while(c>=''&&c<=''){ans=ans*+(c-''); c=getchar();}
return ans*f;
}
int p,n,m,v[M];
int lx[M],rx[M],op[M];
int L,R,mx;
struct pos{int s,h[];}tr[M];
void up(int x){tr[x].s=tr[x<<].s+tr[x<<^].s;}
void down(int x,int l,int r){
if(l==r) return ;
int ls=x<<,rs=x<<^,mid=(l+r)>>;
if(tr[x].h[]){
tr[x].h[]=;
tr[ls].h[]=tr[rs].h[]=;
tr[ls].s=tr[rs].s=;
tr[ls].h[]=tr[rs].h[]=;
}
else if(tr[x].h[]){
tr[x].h[]=; tr[ls].h[]=tr[rs].h[]=;
tr[ls].s=mid-l+; tr[rs].s=r-mid;
tr[ls].h[]=tr[rs].h[]=;
}
}
void build(int x,int l,int r){
tr[x].h[]=tr[x].h[]=;
if(l==r){
tr[x].s=(v[l]>mx);
return ;
}
int mid=(l+r)>>;
build(x<<,l,mid);
build(x<<^,mid+,r);
up(x);
}
void modify(int x,int l,int r,int v){
if(L<=l&&r<=R){
tr[x].h[v]=;
tr[x].h[v^]=;
tr[x].s=(r-l+)*v;
return ;
}
down(x,l,r);
int mid=(l+r)>>;
if(L<=mid) modify(x<<,l,mid,v);
if(R>mid) modify(x<<^,mid+,r,v);
up(x);
}
int query(int x,int l,int r){
if(L<=l&&r<=R) return tr[x].s;
down(x,l,r);
int mid=(l+r)>>,sum=;
if(L<=mid) sum+=query(x<<,l,mid);
if(R>mid) sum+=query(x<<^,mid+,r);
return sum;
}
bool check(int k){
mx=k; build(,,n);
for(int i=;i<=m;i++){
L=lx[i]; R=rx[i];
int ly=query(,,n);
if(op[i]){
if(ly) L=lx[i],R=lx[i]+ly-,modify(,,n,);
if(lx[i]+ly<=rx[i]) L=lx[i]+ly,R=rx[i],modify(,,n,);
}
else{
if(lx[i]<=rx[i]-ly) L=lx[i],R=rx[i]-ly,modify(,,n,);
if(ly) L=rx[i]-ly+,R=rx[i],modify(,,n,);
}
}
L=R=p;
return !query(,,n);
}
int main(){
n=read(); m=read();
for(int i=;i<=n;i++) v[i]=read();
for(int i=;i<=m;i++) op[i]=read(),lx[i]=read(),rx[i]=read();
p=read();
int l=,r=n;
while(l<r){
int mid=(l+r)>>;
if(check(mid)) r=mid;
else l=mid+;
}printf("%d\n",l);
return ;
}

bzoj 4552: [Tjoi2016&Heoi2016]排序——二分+线段树的更多相关文章

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

    [BZOJ4552][Tjoi2016&Heoi2016]排序 Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题 ...

  2. bzoj 4552 [Tjoi2016&Heoi2016]排序 (二分答案 线段树)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4552 题意: 给你一个1-n的全排列,m次操作,操作由两种:1.将[l,r]升序排序,2 ...

  3. BZOJ 4552 [Tjoi2016&Heoi2016]排序 | 二分答案 线段树

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

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

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

  5. bzoj 4552 [Tjoi2016&Heoi2016]排序——二分答案

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4552 二分答案,把 >= mid 的设成1.< mid 的设成0,之后排序就变成 ...

  6. BZOJ 4552: [Tjoi2016&Heoi2016]排序

    4552: [Tjoi2016&Heoi2016]排序 Time Limit: 60 Sec  Memory Limit: 256 MBSubmit: 579  Solved: 322[Sub ...

  7. BZOJ 4552: [Tjoi2016&Heoi2016]排序 线段树 二分

    目录 此代码是个假代码,只能糊弄luogu,以后再改,路过大佬也可以帮一下辣 update 10.6 此代码是个假代码,只能糊弄luogu,以后再改,路过大佬也可以帮一下辣 /* //fang zhi ...

  8. bzoj 4552: [Tjoi2016&Heoi2016]排序【二分+线段树】

    二分值mid,然后把>=mid的赋值为1,其他赋值为0,每次排序就是算出区间内01的个数,然后分别把0和1放到连续的一段内,这些都可以用线段树来维护 二分的判断条件是操作完之后q位置上是否为1 ...

  9. BZOJ 4552 [Tjoi2016&Heoi2016]排序 ——线段树 二分答案

    听说是BC原题. 好题,二分答案变成01序列,就可以方便的用线段树维护了. 然后就是区间查询和覆盖了. #include <map> #include <cmath> #inc ...

随机推荐

  1. 《梦断代码Dreaming In Code》阅读笔记(三)

    最后这几章感觉上更多是从软件完成整体上来讲的.比如说技术.方法等. 在我看来,其实一个团队一直坚持一种好的.先进的方法是不可少的.如果一个优秀的团队刚愎自用,只随着成员们喜好发展,那不能长久.比如说, ...

  2. 福大软工1816 · 第五次作业 - 结对作业2_map与unordered map的比较测试

    测试代码: #include <iostream> using namespace std; #include <string> #include <windows.h& ...

  3. UVALive - 6869 Repeated Substrings 后缀数组

    题目链接: http://acm.hust.edu.cn/vjudge/problem/113725 Repeated Substrings Time Limit: 3000MS 样例 sample ...

  4. 团队作业7——第二次项目冲刺(Beta版本)

    团队作业7——第二次项目冲刺-Beta版本项目计划 团队作业7——第二次项目冲刺(Beta版本)-第一篇 团队作业7——第二次项目冲刺(Beta版本)-第二篇 团队作业7——第二次项目冲刺(Beta版 ...

  5. LintCode-532.逆序对

    逆序对 在数组中的两个数字如果前面一个数字大于后面的数字,则这两个数字组成一个逆序对.给你一个数组,求出这个数组中逆序对的总数. 概括:如果a[i] > a[j] 且 i < j, a[i ...

  6. Django学习笔记---第一天

    Django学习笔记 1.Django的安装 //如果不指定版本号,默认安装最新版 pip3 install django==1.11.8 关于Django的版本和python的版本依赖关系,请看下图 ...

  7. Scala快速入门-基础

    HelloWorld 从HelloWorld开始,使用scala IDE编辑器. 新建scala project 新建scala object 编写HelloWorld run as scala ap ...

  8. Jenkins系列-Jenkins用户权限和角色配置

    由于jenkins默认的权限管理体系不支持用户组或角色的配置,因此需要安装第三发插件来支持角色的配置,这边将使用Role Strategy Plugin,介绍页面:https://wiki.jenki ...

  9. 好记性不如烂笔头之Maven使用小记

    一.前言 说起Maven,是在我上上东家接触的,掌握的还不错,因为种种原因,上家公司没有使用太多大众技术,我也没有太多施展的机会,对于以前掌握的技术,很多都荒废了,最近使用起来发现有点儿吃力了,为了加 ...

  10. matlab padarray

    功能:填充图像或填充数组 使用:B = padarray(A,padsize,padval,direction) A表示输入图像,B是填充后的图像,padsize给出了填充的行数和列数,通常用[r c ...