题面

传送门

分析

此题是道好题!

首先要跳出思维定势,不是去想如何用数据结构去直接维护排序过程,而是尝试二分a[p]的值

设二分a[p]的值为x

我们将大于x的数标记为1,小于等于x的数标记为0

则整个序列只由01组成,记为b

将一个区间升序排序,则相当于将1全部移到右边,0全部移到左边,降序排序反之

例:

a={1,6,5,2,4,3}.x=4

标记后的序列b为{0,1,1,0,0,0}

此时对[1,5]进行升序排序,a={1,2,4,5,6,3}

标记后的序列b为{0,0,0,1,1,0}

因此可以用线段树维护标记后的序列,直接区间求和得到1的个数,再区间更新即可

如果排完序后b[p]=0,则说明a[p]<=x,继续减小x

否则增大x

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 100005
using namespace std;
int n,m,qa;
struct node {
int l;
int r;
int v;
int mark;
int len() {
return r-l+1;
}
} tree[maxn<<2];
int a[maxn];
struct sort_seg {
int l;
int r;
int type;
} q[maxn];
void push_up(int pos) {
tree[pos].v=tree[pos<<1].v+tree[pos<<1|1].v;
}
void build(int l,int r,int pos,int middle) {
tree[pos].l=l;
tree[pos].r=r;
tree[pos].v=0;
tree[pos].mark=-1;
if(l==r) {
tree[pos].v=(a[l]>middle);
return;
}
int mid=(tree[pos].l+tree[pos].r)>>1;
build(l,mid,pos<<1,middle);
build(mid+1,r,pos<<1|1, middle);
push_up(pos);
}
void push_down(int pos) {
if(tree[pos].mark!=-1) {
tree[pos<<1].mark=tree[pos].mark;
tree[pos<<1|1].mark=tree[pos].mark;
tree[pos<<1].v=tree[pos].mark*tree[pos<<1].len();
tree[pos<<1|1].v=tree[pos].mark*tree[pos<<1|1].len();
tree[pos].mark=-1;
}
}
void update(int L,int R,int v,int pos) {
if(R<tree[pos].l||L>tree[pos].r) return;
if(L<=tree[pos].l&&R>=tree[pos].r) {
tree[pos].v=v*tree[pos].len();
tree[pos].mark=v;
return;
}
push_down(pos);
int mid=(tree[pos].l+tree[pos].r)>>1;
if(L<=mid) update(L,R,v,pos<<1);
if(R>mid) update(L,R,v,pos<<1|1);
push_up(pos);
}
int query(int L,int R,int pos) {
if(R<tree[pos].l||L>tree[pos].r) return 0;
if(L<=tree[pos].l&&R>=tree[pos].r) {
return tree[pos].v;
}
push_down(pos);
int mid=(tree[pos].l+tree[pos].r)>>1;
int ans=0;
if(L<=mid) ans+=query(L,R,pos<<1);
if(R>mid) ans+=query(L,R,pos<<1|1);
return ans;
}
int check(int x) {
build(1,n,1,x);
for(int i=1; i<=m; i++) {
int sum=query(q[i].l,q[i].r,1);
if(q[i].type==0) {
update(q[i].l,q[i].r-sum,0,1);
update(q[i].r-sum+1,q[i].r,1,1);
} else {
update(q[i].l,q[i].l+sum-1,1,1);
update(q[i].l+sum,q[i].r,0,1);
}
}
if(query(qa,qa,1)==1) return 0;
else return 1;
}
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",&q[i].type,&q[i].l,&q[i].r);
}
int l=1,r=n;
int ans=n+1;
scanf("%d",&qa);
while(l<=r) {
int mid=(l+r)>>1;
if(check(mid)) {
ans=min(ans,mid);
r=mid-1;
} else {
l=mid+1;
}
}
printf("%d\n",ans);
}

BZOJ 4552(二分+线段树+思维)的更多相关文章

  1. HDU4614 Vases and Flowers 二分+线段树

    分析:感觉一看就是二分+线段树,没啥好想的,唯一注意,当开始摆花时,注意和最多能放的比大小 #include<iostream> #include<cmath> #includ ...

  2. BZOJ.4184.shallot(线段树分治 线性基)

    BZOJ 裸的线段树分治+线性基,就是跑的巨慢_(:з」∠)_ . 不知道他们都写的什么=-= //41652kb 11920ms #include <map> #include < ...

  3. J - Joseph and Tests Gym - 102020J (二分+线段树)

    题目链接:https://cn.vjudge.net/contest/283920#problem/J 题目大意:首先给你n个门的高度,然后q次询问,每一次询问包括两种操作,第一种操作是将当前的门的高 ...

  4. Educational Codeforces Round 61 D 二分 + 线段树

    https://codeforces.com/contest/1132/problem/D 二分 + 线段树(弃用结构体型线段树) 题意 有n台电脑,只有一个充电器,每台电脑一开始有a[i]电量,每秒 ...

  5. 【BZOJ-3110】K大数查询 整体二分 + 线段树

    3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6265  Solved: 2060[Submit][Sta ...

  6. hdu6070 Dirt Ratio 二分+线段树

    /** 题目:hdu6070 Dirt Ratio 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6070 题意:给定n个数,求1.0*x/y最小是多少.x ...

  7. [BZOJ 4025]二分图(线段树分治+带边权并查集)

    [BZOJ 4025]二分图(线段树分治+带边权并查集) 题面 给出一个n个点m条边的图,每条边会在时间s到t出现,问每个时间的图是否为一个二分图 \(n,m,\max(t_i) \leq 10^5\ ...

  8. K-th occurrence HDU - 6704 (后缀数组+二分线段树+主席树)

    大意: 给定串s, q个询问(l,r,k), 求子串s[l,r]的第kk次出现位置. 这是一篇很好的题解: https://blog.csdn.net/sdauguanweihong/article/ ...

  9. BZOJ.4552.[HEOI2016/TJOI2016]排序(线段树合并/二分 线段树)

    题目链接 对于序列上每一段连续区间的数我们都可以动态开点建一棵值域线段树.初始时就是\(n\)棵. 对于每次操作,我们可以将\([l,r]\)的数分别从之前它所属的若干段区间中分离出来,合并. 对于升 ...

随机推荐

  1. Node.js企业开发:应用场景

    要想用Node.js首先需要知道它到底是什么, 有哪些优缺点. 然后我们才能知道到底 Node.js 适合哪些应用场景. Node.js 维基百科:“Node.js 是谷歌 V8 引擎.libuv平台 ...

  2. 带加载进度的Web图片懒加载组件Lazyload

    在Web项目中,大量的图片应用会导致页面加载时间过长,浪费不必要的带宽成本,还会影响用户浏览体验. Lazyload 是一个文件大小仅4kb的图片懒加载组件(不依赖其它第三方库),组件会根据用户当前浏 ...

  3. :last-child----represents the last element among a group of sibling elements.

    CSS伪类 :last-child 代表在一群兄弟元素中的最后一个元素. 举个例子: 从代码和图可以看出:last-child选择了最后一个li标签. 同时,我们换另外一段代码,看看是否还有这样的效果 ...

  4. 【NOIP2016提高A组模拟8.14】疯狂的火神

    题目 火神为了检验zone的力量,他决定单挑n个人. 由于火神训练时间有限,最多只有t分钟,所以他可以选择一部分人来单挑,由于有丽子的帮助,他得到了每个人特定的价值,每个人的价值由一个三元组(a,b, ...

  5. margin属性以及垂直外边距重叠问题

       盒子的margin属性         盒子的外边距margin 指的是当前盒子与其他盒子之间的距离,环绕在盒子周围的空白区域,属于不可见的区域,,不会影响到可见框的大小,而是会影响到盒子的位置 ...

  6. 12 Spring Boot密码加密算法

  7. HDU1232 畅通工程(并查集)

    #include<iostream> using namespace std; ]; int findx(int x) { while(num[x]!=x)x=num[x]; return ...

  8. vue使用过滤器 filters:{}

    在项目开发过程中,经常会用到过滤器,下面就来说说我用的用法 我从后台获取到一个时间字段,是2017-03-23的格式,但是我要的是年月日分开显示,那就要用到过滤器了 在没有用过滤器的时候,是这样的: ...

  9. IDEA将maven项目配置到本地tomcat中运行

    1. Run->Edit Configurations 2. 点开default,选择tomcatServer选择local 3. 点解server选项卡下的configure,配置本地tomc ...

  10. node.js运行配置(vs code非控制台输出)

    node.js运行配置(vs code非控制台输出) node  配置 简化  vs code 是非常强大的编译器,皆因它有有各种各样好用的插件. 在没有安装code runner插件之前,想要执行n ...