bzoj4552排序(线段树,二分)
题目大意
给定一个长度为n的序列,有m个操作,操作包括两种:
\(0\ l\ r\)区间[l,r]的数字升序排序
\(1\ l\ r\)区间[l,r]的数字降序排序
最后询问在q位置上的数是多少?
其中\(n \le 100000,m\le 100000\)
QWQ这个题是看了题解才会的,感觉思路很不错
我们考虑,这个题的询问其实只有一组,所以我们可以 二分一个最终在q的数是多少(或者说在原来的排名是多少)
每次将大于等于\(mid\)的数变为1,小于的为0。
那么对于升序排序,假设这个区间有\(tot\)个1,
我们就可以将\([r-tot+1,r]\)赋值为1,将剩余区间赋值为0
而降序排序呢,我们就可以将\([l,l+tot-1]\)赋值为1,其余为0
这样就将“排序“ ---->“区间赋值”:
那么,我们不难想到!!!线段树!!!
只需要最后我们看一下第q个数是不是1就可以,如果是1,我们可以稍微加大mid,不然就减少mid
上代码
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>
#include<queue>
#include<vector>
using namespace std;
inline int read()
{
int x=0,f=1;char ch=getchar();
while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
while (isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
return x*f;
}
const int maxn = 100100;
int f[4*maxn];
int add[4*maxn];
int n,m,a[maxn];
int x[maxn],y[maxn],z[maxn];
int c[maxn];
int l,r;
int ques;
void up(int root)
{
f[root]=f[2*root]+f[2*root+1];
}
void pushdown(int root,int l,int r)
{
int mid = (l+r) >> 1;
if (add[root]!=-1)
{
add[2*root]=add[root];
add[2*root+1]=add[root];
f[2*root]=(mid-l+1)*add[root];
f[2*root+1]=(r-mid)*add[root];
add[root]=-1;
}
}
void build(int root,int l,int r)
{
add[root]=-1;
if (l==r)
{
f[root]=a[l];
return;
}
int mid =(l+r) >> 1;
build(2*root,l,mid);
build(2*root+1,mid+1,r);
up(root);
}
void update(int root,int l,int r,int x,int y,int p)
{
if (l>r || x>y) return;
if (x<=l && r<=y)
{
add[root]=p;
f[root]=(r-l+1)*add[root];
return;
}
pushdown(root,l,r);
int mid = (l+r) >> 1;
if (x<=mid) update(2*root,l,mid,x,y,p);
if (y>mid) update(2*root+1,mid+1,r,x,y,p);
up(root);
}
int query(int root,int l,int r,int x,int y)
{
if (l>r || x>y) return 0;
if (x<=l && r<=y)
{
return f[root];
}
pushdown(root,l,r);
int mid = (l+r) >> 1;
int ans=0;
if (x<=mid) ans=ans+query(2*root,l,mid,x,y);
if (y>mid) ans=ans+query(2*root+1,mid+1,r,x,y);
return ans;
}
bool check(int mid)
{
memset(a,-1,sizeof(a));
for (int i=1;i<=n;i++)
if (c[i]>=mid) a[i]=1;
else a[i]=0;
build(1,1,n);
for (int i=1;i<=m;i++)
{
int tot=query(1,1,n,x[i],y[i]);
if (z[i]==0)
{
update(1,1,n,y[i]-tot+1,y[i],1);
update(1,1,n,x[i],y[i]-tot,0);
}
else
{
update(1,1,n,x[i],x[i]+tot-1,1);
update(1,1,n,x[i]+tot,y[i],0);
}
}
if (query(1,1,n,ques,ques)==1) return true;
else false;
}
int ans;
int main()
{
scanf("%d%d",&n,&m);
l=1;
r=n;
for (int i=1;i<=n;i++) c[i]=read();
for (int i=1;i<=m;i++)
{
z[i]=read();
x[i]=read();
y[i]=read();
}
ques=read();
//二分这个位置上的数是多少
while (l<=r)
{
int mid = (l+r) >> 1;
if (check(mid)) l=mid+1,ans=mid;
else r=mid-1;
}
cout<<ans;
return 0;
}
bzoj4552排序(线段树,二分)的更多相关文章
- 洛谷$P2824\ [HEOI2016/TJOI2016]$ 排序 线段树+二分
正解:线段树+二分 解题报告: 传送门$QwQ$ 昂着题好神噢我$jio$得$QwQQQQQ$,,, 开始看到长得很像之前考试题的亚子,,,然后仔细康康发现不一样昂$kk$,就这里范围是$[1,n]$ ...
- BZOJ4552:[TJOI2016&HEOI2016]排序(线段树,二分)
Description 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他. 这个难题是这样子的:给出一个1到n的全排列,现在对这 ...
- [HEOI2016/TJOI2016]排序 线段树+二分
[HEOI2016/TJOI2016]排序 内存限制:256 MiB 时间限制:6000 ms 标准输入输出 题目类型:传统 评测方式:文本比较 题目描述 在2016年,佳媛姐姐喜欢上了数字序列.因而 ...
- [Luogu P2824] [HEOI2016/TJOI2016]排序 (线段树+二分答案)
题面 传送门:https://www.luogu.org/problemnew/show/P2824 Solution 这题极其巧妙. 首先,如果直接做m次排序,显然会T得起飞. 注意一点:我们只需要 ...
- BZOJ 4552: [Tjoi2016&Heoi2016]排序 线段树 二分
目录 此代码是个假代码,只能糊弄luogu,以后再改,路过大佬也可以帮一下辣 update 10.6 此代码是个假代码,只能糊弄luogu,以后再改,路过大佬也可以帮一下辣 /* //fang zhi ...
- BZOJ 4552 [Tjoi2016&Heoi2016]排序 ——线段树 二分答案
听说是BC原题. 好题,二分答案变成01序列,就可以方便的用线段树维护了. 然后就是区间查询和覆盖了. #include <map> #include <cmath> #inc ...
- 2021.12.09 [HEOI2016/TJOI2016]排序(线段树+二分,把一个序列转换为01串)
2021.12.09 [HEOI2016/TJOI2016]排序(线段树+二分,把一个序列转换为01串) https://www.luogu.com.cn/problem/P2824 题意: 在 20 ...
- Codeforces Gym 100231B Intervals 线段树+二分+贪心
Intervals 题目连接: http://codeforces.com/gym/100231/attachments Description 给你n个区间,告诉你每个区间内都有ci个数 然后你需要 ...
- luogu4422 [COCI2017-2018#1] Deda[线段树二分]
讨论帖:线段树二分的题..我还考场切过..白学 这题我一年前的模拟赛考场还切过,现在就不会了..好菜啊. 显然直接线段树拆成$\log n$个区间,然后每个区间在进行线段树二分即可. UPD:复杂度分 ...
- [BZOJ 2653] middle(可持久化线段树+二分答案)
[BZOJ 2653] middle(可持久化线段树+二分答案) 题面 一个长度为n的序列a,设其排过序之后为b,其中位数定义为b[n/2],其中a,b从0开始标号,除法取下整. 给你一个长度为n的序 ...
随机推荐
- 用tinyxml2读写xml文件_C++实现
下载源代码 开源代码github地址: https://github.com/leethomason/tinyxml2 添加工程文件 将源代码目录中 tinyxml2.h 和 tinyxml2.cpp ...
- 174道 JavaScript 面试题,助你查漏补缺
最近在整理 JavaScript 的时候发现遇到了很多面试中常见的面试题,本部分主要是作者在 Github 等各大论坛收录的 JavaScript 相关知识和一些相关面试题时所做的笔记,分享这份总结给 ...
- Qt5-调试器安装
这周末正好有空,我好好研究了下如何给Qt安装调试器.我们在windows下一般安装两种Qt版本,一种是基于Visual Stuido编译器的(MSVC),另一种是基于g++的MinGW.使用后者一般调 ...
- 文件权限的管理以及acl权限列表
ls -l? 文件名称 上面的命令以长格式显示文件与目录,每一行都是一个文件或目录的属性数据,每个文件或子目录的属性数据又以7个字段显示,各个字段的说明如下: (1)文件类型与权限:该字段共有10个字 ...
- 问题:idea 中文无法使用
1. 问题--idea无法使用中文输入 原因:idea本身版本过高,所以需要你强制减低它的jdk版本 解决:使用配置idea环境变量解决 ps:目前适用于任何版本的jdk和idea 步骤: 1.新建 ...
- skynet 开启 https 配置
修改 Makefile Mac 下: # https : turn on TLS_MODULE to add https support TLS_MODULE=ltls TLS_LIB="$ ...
- 二、grep文本搜索工具
grep命令作为Unix中用于文本搜索的神奇工具,能够接受正则表达式,生成各种格式的输出.除此外,它还有大量有趣的选项. # 搜索包含特定模式的文本行: [root@centos8 ~]#grep p ...
- 2021秋 noip 模拟赛
9.9 T3 第负二题 \(f_i\) 的数学意义:中心在第 \(i\) 行的全 \(1\) 组成的最大正方形(对角线水平/竖直),对角线长 \(2f_i-1\). 显然 \(f_i\) 具有单调性( ...
- IS(上升子序列)
前言: 这是一篇杂题选讲+作者口胡的博客,不喜勿喷. 正文: 提示:在阅读时请留意加粗的字体是"极长"还是"最长". 今天改题时碰到了一道关于线段树 ...
- shell脚本测试变量是否为空,测试文件是否存在,sed修改配置文件参数,分支语句
Shell脚本 1. 基本的几个变量 使用$?获取最近一次的执行结果: 使用$#获取传递的参数个数,类似C语言中的int argc; 使用$@获取所有的传参,类似C语言的char **argv 2. ...