题面

传送门

分析

此题是道好题!

首先要跳出思维定势,不是去想如何用数据结构去直接维护排序过程,而是尝试二分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. Python内置函数之filter map reduce

    Python内置函数之filter map reduce 2013-06-04 Posted by yeho Python内置了一些非常有趣.有用的函数,如:filter.map.reduce,都是对 ...

  2. 【CF487E】Tourists

    洛谷链接 题意 给定一张无向图,点有点权,多次询问两点之间路径上点权最小的点的可能的最小值,支持修改点权. Sol 一棵树就很简单 , 于是我们考虑点双(环)上的情况 , 直观想法就是缩完点双后一个点 ...

  3. git的初步研究1

    工作中很多项目再往git上迁移,所以打算研究下git git是个版本控制系统 理解git工作区.暂存区.版本库的概念 工作区:在电脑中能看到的目录 暂存区:index即索引 即首先add加入暂存区 c ...

  4. 安卓手机通过有线连接PC上网

    因手机wifi坏了,速度上限为2.5m/s.无法发挥出100m带宽的威力. 这里探索各大神的指导,记录下其中一种方式. :链接       主题:使用openvpn和手机的USB共享网络 通过mico ...

  5. linux运维、架构之路-Lamp架构部署

    一.Lamp架构原理 二.Lamp架构软件安装 1.apache安装脚本 #!/bin/sh cd /server/tools/ yum install zlib-devel -y wget http ...

  6. HDU 3341 Lost's revenge ( Trie图 && 状压DP && 数量限制类型 )

    题意 : 给出 n 个模式串,最后给出一个主串,问你主串打乱重组的情况下,最多能够包含多少个模式串. 分析 : 如果你做过类似 Trie图 || AC自动机 + DP 类似的题目的话,那么这道题相对之 ...

  7. Java——开发环境配置

    [1]JDK的安装与卸载 (1)卸载程序         控制面板--添加或删除程序--J2SE Development Kit和J2SE Runtime Envioroment--删除 (2)安装程 ...

  8. Are We Ready for SDN? Implementation Challenges for Software-Defined Networks

    Name of article:Are We Ready for SDN?  Implementation Challenges for  Software-Defined Networks Orig ...

  9. ASP.NET MVC 下拉的使用(ViewData传递)

    C#部分 public void GetViewData() { List<string> data = new List<string>(); data.Add(" ...

  10. CSS基础-background的那些属性

    background的那些属性 background:背景的意思常用的六个属性 1.background-color:背景颜色 2.background-image:背景图像 3.background ...