题目描述

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

输入格式

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

输出格式

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

说明/提示

河北省选2016第一天第二题。

对于30%的数据,\(n,m\leq 1000\)

对于100%的数据,n,m\leq 10^5$

且始终\(1\leq q\leq n\)


二分+线段树

二分q上的答案

对于大于mid的数,全部改成1,其它则为0

排序操作看成是对01序列排序

即可转化成线段树的区间修改

每次询问区间上多少个1,按照排序规则对区间赋值

O(nlog(n)log(n))

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
const int N=3e5+10;
struct node{
int op,l,r;
}e[N*5];
int A[N],q;
int n,m,x;
#define ls (p<<1)
#define rs (p<<1|1)
struct E{
int l,r,sum;
int op;
#define l(x) tree[x].l
#define r(x) tree[x].r
#define sum(x) tree[x].sum
}tree[N];
inline void build(int p,int l,int r){
l(p)=l;r(p)=r;
if(l==r){
sum(p)= A[l]>=x;
tree[p].op=0;
return;
}
int mid=(l+r)>>1;
build(ls,l,mid);
build(rs,mid+1,r);
sum(p)=sum(ls)+sum(rs);
tree[p].op=0;
}
inline void pushdown(int p){
if(tree[p].op==0)return;
sum(ls)=(r(ls)-l(ls)+1)*(tree[p].op-1);
sum(rs)=(r(rs)-l(rs)+1)*(tree[p].op-1);
tree[ls].op=tree[p].op;
tree[rs].op=tree[p].op;
tree[p].op=0;
}
inline void change(int p,int l,int r,int d){
if(l>r)return;
if(l<=l(p)&&r(p)<=r){
sum(p)=d*(r(p)-l(p)+1);
tree[p].op=d+1;
return;
}
if(l>r(p)||r<l(p))return;
pushdown(p);
int mid=(l(p)+r(p))>>1;
if(l<=mid)change(ls,l,r,d);
if(r>mid)change(rs,l,r,d);
sum(p)=sum(ls)+sum(rs);
}
inline int ask(int p,int l,int r){
if(l<=l(p)&&r(p)<=r)return sum(p);
if(l>r(p)||r<l(p))return 0;
pushdown(p);
int ans=0;
ans+=ask(ls,l,r);
ans+=ask(rs,l,r);
return ans;
}
inline bool check(){ build(1,1,n);
for(int i=1;i<=m;i++){
int op=e[i].op,l=e[i].l,r=e[i].r;
int sum=ask(1,l,r);
if(op){
if(sum>0)change(1,l,l+sum-1,1);
change(1,l+sum,r,0);
}else{
if(sum<(r-l+1))change(1,l,r-sum,0);
change(1,r-sum+1,r,1);
}
}
return ask(1,q,q);
}
int main(){ cin>>n>>m;
int Min=1e9,Max=0;
for(int i=1;i<=n;i++){
scanf("%d",&A[i]);
Max=max(Max,A[i]);
Min=min(Min,A[i]);
}
for(int i=1;i<=m;i++)
scanf("%d%d%d",&e[i].op,&e[i].l,&e[i].r);
cin>>q;
int l=Min,r=Max,ans=-1;
while(l<=r){
x=(l+r)>>1;
if(check()){
l=x+1;
ans=x;
}else{
r=x-1;
}
}
cout<<ans<<endl;
}

luogu P2824 [HEOI2016/TJOI2016]排序的更多相关文章

  1. [Luogu P2824] [HEOI2016/TJOI2016]排序 (线段树+二分答案)

    题面 传送门:https://www.luogu.org/problemnew/show/P2824 Solution 这题极其巧妙. 首先,如果直接做m次排序,显然会T得起飞. 注意一点:我们只需要 ...

  2. Luogu P2824 [HEOI2016/TJOI2016]排序 线段树+脑子

    只会两个$log$的$qwq$ 我们二分答案:设答案为$ans$,则我们把$a[i]<=ans$全部设成$0$,把$a[i]>ans$全部设成$1$,扔到线段树里,这样区间排序(升序)就是 ...

  3. 「Luogu P2824 [HEOI2016/TJOI2016]排序」

    一道十分神奇的线段树题,做法十分的有趣. 前置芝士 线段树:一个十分基础的数据结构,在这道题中起了至关重要的作用. 一种基于01串的神奇的二分思想:在模拟赛中出现了这道题,可以先去做一下,这样可能有助 ...

  4. 洛谷 P2824 [HEOI2016/TJOI2016]排序 解题报告

    P2824 [HEOI2016/TJOI2016]排序 题意: 有一个长度为\(n\)的1-n的排列\(m\)次操作 \((0,l,r)\)表示序列从\(l\)到\(r\)降序 \((1,l,r)\) ...

  5. [洛谷P2824][HEOI2016/TJOI2016]排序

    题目大意:一个全排列,两种操作: 1. $0\;l\;r:$把$[l,r]$升序排序2. $1\;l\;r:$把$[l,r]$降序排序 最后询问第$k$位是什么 题解:二分答案,把比这个数大的赋成$1 ...

  6. Luogu 2824 [HEOI2016/TJOI2016]排序

    BZOJ 4552 挺妙的解法. 听说这题直接用一个桶能拿到$80 \ pts$ 发现如果是一个排列的话,要对这个序列排序并不好做,但是假如是$01$序列的话,要对一个区间排序还是很简单的. 发现最后 ...

  7. 洛谷P2824 [HEOI2016/TJOI2016]排序(线段树)

    传送门 这题的思路好清奇 因为只有一次查询,我们考虑二分这个值为多少 将原序列转化为一个$01$序列,如果原序列上的值大于$mid$则为$1$否则为$0$ 那么排序就可以用线段树优化,设该区间内$1$ ...

  8. 洛谷 P2824 [HEOI2016/TJOI2016]排序 (线段树合并)

    (另外:题解中有一种思路很高妙而且看上去可以适用一些其他情况的离线方法) 线段树合并&复杂度的简单说明:https://blog.csdn.net/zawedx/article/details ...

  9. 洛谷$P2824\ [HEOI2016/TJOI2016]$ 排序 线段树+二分

    正解:线段树+二分 解题报告: 传送门$QwQ$ 昂着题好神噢我$jio$得$QwQQQQQ$,,, 开始看到长得很像之前考试题的亚子,,,然后仔细康康发现不一样昂$kk$,就这里范围是$[1,n]$ ...

随机推荐

  1. js中 对象名.属性名和对象名['属性名']的区别,.和[]的区别

    对象中的对象名[ ' 属性名 ' ] 和 对象名.属性名的区别 话不多少,上图分析,菜鸟刚学几个月,如有错误,欢迎大佬们指出 这里是很显而易见的! 然后我们用for in 对他进行遍历,他的区别就出来 ...

  2. 利用DI实现级联删除 - xms跨平台基础框架 - 基于.netcore

    一.引言 所谓级联删除是指删除一条记录后,附带关联记录也一起删除,比如删除客户后,联系人也一起删除: 以往我们会依赖于数据库表的外键约束,但存在着明显的问题,增加数据库压力.提示不友好.职责越界.事务 ...

  3. getchar()用法 【转】

    1.从缓冲区读走一个字符,相当于清除缓冲区 2.前面的scanf()在读取输入时会在缓冲区中留下一个字符'\n'(输入完s[i]的值后按回车键所致),所以如果不在此加一个getchar()把这个回车符 ...

  4. SqlServer2005 查询 第二讲 distinct

    今天我们来说distinct关键字的用法. distinct - distinct:我们可以这样理解成[过滤重复值] - select distinct deptno from emp // -- 首 ...

  5. SqlServer2005 查询 第一讲 计算列

    数据库查询[最重要且在数据库中难度最大] 声明一下我这里用的数据库样例是郝斌老师的(scott库) 我尽最大努力把复杂的问题简单化,方便理解,希望我写的东西能够帮助到你们 有些复杂的东西我我用自己的方 ...

  6. virtualBox里Ubuntu设置静态IP

    1.先将网络设置为桥接模式 2.打开虚拟机,进入界面,点击编辑 3.设置IP,ipconfig/all查看物理机IP,虚拟机要与本机在同一网段 然后断开重新连接就可以上网了

  7. pat 1050 String Subtraction(20 分)

    1050 String Subtraction(20 分) Given two strings S​1​​ and S​2​​, S=S​1​​−S​2​​ is defined to be the ...

  8. 从壹开始 [ Design Pattern ] 之二 ║ 单例模式 与 Singleton

    前言 这一篇来源我的公众号,如果你没看过,正好直接看看,如果看过了也可以再看看,我稍微修改了一些内容,今天讲解的内容如下: 一.什么是单例模式 [单例模式],英文名称:Singleton Patter ...

  9. 在SQL Server数据库中执行存储过程很快,在c#中调用很慢的问题

    记录工作中遇到的问题,分享出来: 原博客地址:https://blog.csdn.net/weixin_40782680/article/details/85038281 今天遇到一个比较郁闷的问题, ...

  10. jinjia2

    ansible-playbook --become --become-method=su -K copy.yml - hosts: web remote_user: ansible tasks: - ...