题目描述

在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;
}

最新文章

  1. nodejs 笔记
  2. python模块之subprocess
  3. Python list嵌套 三维数组
  4. 双击防止网页放大缩小HTML5
  5. C语言中两位ASCII码可以表示汉字
  6. http协议.md
  7. 移动零售批发行业新的技术特色-智能PDA手持移动扫描打印销售开单收银仪!!
  8. HDU 5514 Frogs (容斥原理)
  9. JAVA获取oracle中sequences的最后一个值
  10. SharePoint迁移数据到生产环境
  11. 【Js应用实例】限制上传图片大小
  12. 记录兼容IE8中发现的一些问题
  13. 独立成分分析(ICA)的模拟实验(R语言)
  14. RFM模型及R语言实现
  15. 开发快平台(M302I小e开发板系列教程)
  16. Unity 原厂免费资源学习
  17. PowerDesigner 物理数据模型(PDM) 说明
  18. 浅谈 volatile 的实现原理
  19. js event
  20. JavaScript 中this的实现原理

热门文章

  1. NOIP模拟27(命悬一线)
  2. JVM初体验
  3. egret编译速度慢解决方法
  4. java线程池的介绍与使用(Executor框架)
  5. [笔记] HOW2J.CN网站记录的java笔记_第四部分_HTML
  6. hdu 1874 畅通工程续 (dijkstra(不能用于负环))
  7. CMake 常用函数记录
  8. 使用Java窗口程序执行输入的任何cmd命令
  9. Swoft 源码剖析 - Swoole和Swoft的那些事 (Http/Rpc服务篇)
  10. 最省钱的爬虫解决方案,比IP代理更划算