BZOJ 4552(二分+线段树+思维)
题面
分析
此题是道好题!
首先要跳出思维定势,不是去想如何用数据结构去直接维护排序过程,而是尝试二分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(二分+线段树+思维)的更多相关文章
- HDU4614 Vases and Flowers 二分+线段树
分析:感觉一看就是二分+线段树,没啥好想的,唯一注意,当开始摆花时,注意和最多能放的比大小 #include<iostream> #include<cmath> #includ ...
- BZOJ.4184.shallot(线段树分治 线性基)
BZOJ 裸的线段树分治+线性基,就是跑的巨慢_(:з」∠)_ . 不知道他们都写的什么=-= //41652kb 11920ms #include <map> #include < ...
- J - Joseph and Tests Gym - 102020J (二分+线段树)
题目链接:https://cn.vjudge.net/contest/283920#problem/J 题目大意:首先给你n个门的高度,然后q次询问,每一次询问包括两种操作,第一种操作是将当前的门的高 ...
- Educational Codeforces Round 61 D 二分 + 线段树
https://codeforces.com/contest/1132/problem/D 二分 + 线段树(弃用结构体型线段树) 题意 有n台电脑,只有一个充电器,每台电脑一开始有a[i]电量,每秒 ...
- 【BZOJ-3110】K大数查询 整体二分 + 线段树
3110: [Zjoi2013]K大数查询 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6265 Solved: 2060[Submit][Sta ...
- hdu6070 Dirt Ratio 二分+线段树
/** 题目:hdu6070 Dirt Ratio 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6070 题意:给定n个数,求1.0*x/y最小是多少.x ...
- [BZOJ 4025]二分图(线段树分治+带边权并查集)
[BZOJ 4025]二分图(线段树分治+带边权并查集) 题面 给出一个n个点m条边的图,每条边会在时间s到t出现,问每个时间的图是否为一个二分图 \(n,m,\max(t_i) \leq 10^5\ ...
- K-th occurrence HDU - 6704 (后缀数组+二分线段树+主席树)
大意: 给定串s, q个询问(l,r,k), 求子串s[l,r]的第kk次出现位置. 这是一篇很好的题解: https://blog.csdn.net/sdauguanweihong/article/ ...
- BZOJ.4552.[HEOI2016/TJOI2016]排序(线段树合并/二分 线段树)
题目链接 对于序列上每一段连续区间的数我们都可以动态开点建一棵值域线段树.初始时就是\(n\)棵. 对于每次操作,我们可以将\([l,r]\)的数分别从之前它所属的若干段区间中分离出来,合并. 对于升 ...
随机推荐
- bzoj4025 二分图 LCT + 最小生成树
题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4025 题解 貌似这道题有一个非常简单的做法是线段树分治+并查集. 可是我是为了练 LCT 来做 ...
- 转 Java中final、finally、finalize的区别与用法
Java中final.finally.finalize的区别与用法 1.简单区别:final用于声明属性,方法和类,分别表示属性不可交变,方法不可覆盖,类不可继承.finally是异常处理语句结构 ...
- zip(), dict(), itertools.repeat(), list(迭代器)
*. zip(), dict() def demo_zip_dict(): keys = ['a', 'b', 'c'] values = [1, 2, 3] entrys = zip(keys, v ...
- Python操作 Excel表格
python 读写 excel 有好多选择,但是,方便操作的库不多,在我尝试了几个库之后,我觉得两个比较方便的库分别是 xlrd/xlwt.openpyxl. 我使用openpyxl 安装: pip ...
- ASP.NET实现大文件上传和下载
总结一下大文件分片上传和断点续传的问题.因为文件过大(比如1G以上),必须要考虑上传过程网络中断的情况.http的网络请求中本身就已经具备了分片上传功能,当传输的文件比较大时,http协议自动会将文件 ...
- [CF1177B]Digits Sequence (Hard Edition)题解
一个简单的模拟,首先先计算当前是几位数,然后根据几位数推断当前的数是什么,然后求出该位即可 #include <cstdio> int main(){ long long k; scanf ...
- es之关于consistency(数据一致性问题)
Es集群内部是有一个约定是用来约束我们的写操作的,就是“一致性”: 也就是说:新建.索引.删除这些操作都是写操作,他们都有一个大前提: 当前的分片副本处于活跃状态的数量 >= int( (pri ...
- Kaggle 入门资料
kaggle入门之如何使用 - CSDN博客 http://blog.csdn.net/mdjxy63/article/details/78221955 kaggle比赛之路(一) -- 新手注册账号 ...
- ijkplayer阅读学习笔记之从代码上看播放流程
http://blog.csdn.net/i_do_can/article/details/51374732
- Visual Studio使用技巧 +谷歌浏览器使用技巧总结
一.总结下visual studio常用的使用技巧,有助于提高效率: 1.给代码行打标记: ctrl + K :给行打标记:ctrl + K + N:切换标记,即使当前页关闭了,也可以适用此快捷键快 ...