题目链接

  震惊!两个线段树和一个线段树竟是50分的差距!

  本题可以使用二分答案,二分那个位置上最后是什么数。怎么验证呢?

  把原序列改变,大于等于mid的全部变成1,小于mid的全部变成0,之后线段树排序。

  最后看那个位置上是1还是0,若是1则说明最后那个位置上是个>=mid的数。

#include<cstdio>
#include<cctype>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#define left (rt<<1)
#define right (rt<<1|1)
#define mid ((l+r)>>1)
#define lson l,mid,left
#define rson mid+1,r,right
#define maxn 300030
using namespace std;
inline long long read(){
long long num=,f=;
char ch=getchar();
while(!isdigit(ch)){
if(ch=='-') f=-;
ch=getchar();
}
while(isdigit(ch)){
num=num*+ch-'';
ch=getchar();
}
return num*f;
} struct Que{
int opt,from,to;
}q[maxn]; int d[maxn],w[maxn]; int tree[maxn*],mem[maxn*],tag[maxn*];
inline void pushup(int rt){ tree[rt]=tree[left]+tree[right]; }
inline void build(int l,int r,int rt){
tree[rt]=mem[rt]=tag[rt]=;
if(l==r){
tree[rt]=w[l];
//printf("%d %d\n",l,w[l]);
return;
}
build(lson);
build(rson);
pushup(rt);
}
inline void pushdown(int rt,int m){
if(mem[rt]==&&tag[rt]==) return;
if(mem[rt]){
mem[left]=mem[right]=;
tree[left]=tree[right]=;
tag[left]=tag[right]=;
mem[rt]=;
}
if(tag[rt]){
tag[left]+=tag[rt]; tag[right]+=tag[rt];
tree[left]+=m-(m>>);
tree[right]+=m>>;
tag[rt]=;
}
return;
}
void update(int from,int to,int l,int r,int rt){
if(from<=l&&to>=r){
tag[rt]++;
tree[rt]+=r-l+;
return;
}
pushdown(rt,r-l+);
if(from<=mid) update(from,to,lson);
if(to>mid) update(from,to,rson);
pushup(rt);
}
void memdate(int from,int to,int l,int r,int rt){
if(from<=l&&to>=r){
tag[rt]=; mem[rt]=;
tree[rt]=;
return;
}
pushdown(rt,r-l+);
if(from<=mid) memdate(from,to,lson);
if(to>mid) memdate(from,to,rson);
pushup(rt);
}
int query(int from,int to,int l,int r,int rt){
if(from<=l&&to>=r) return tree[rt];
pushdown(rt,r-l+);
int ans=;
if(from<=mid) ans+=query(from,to,lson);
if(to>mid) ans+=query(from,to,rson);
return ans;
} bool check(int lim,int n,int m,int last){
build(,n,);
for(int i=;i<=m;++i){
int opt=q[i].opt,from=q[i].from,to=q[i].to;
int c1=query(from,to,,n,);
int c2=to-from+-c1;
//printf("%d %d<<\n",c1,c2);
memdate(from,to,,n,);
if(opt==) update(from+c2,to,,n,);
else update(from,from+c1-,,n,);
}
//printf("zero\n");
//for(int i=1;i<=n;++i) printf("%d ",zero.query(i,i,1,n,1));
//printf("\none\n");
//for(int i=1;i<=n;++i) printf("%d ",one.query(i,i,1,n,1));
//printf("\n");
return query(last,last,,n,);
} int main(){
int n=read(),m=read();
for(int i=;i<=n;++i) d[i]=read();
for(int i=;i<=m;++i) q[i]=(Que){read(),read(),read()};
int last=read();
int l=,r=n,ans=;
while(l<=r){
//printf("%d %d %d\n",l,r,mid);
for(int i=;i<=n;++i)
if(d[i]>=mid) w[i]=;
else w[i]=;
//for(int i=1;i<=n;++i) printf("%d<",w[i]);
//printf("\n");
if(check(mid,n,m,last)){
ans=mid;
l=mid+;
}
else r=mid-;
}
printf("%d",ans);
return ;
}

【Luogu】P2824排序(二分答案+线段树排序)的更多相关文章

  1. [BZOJ4552][TJOI2016&&HEOI2016]排序(二分答案+线段树/线段树分裂与合并)

    解法一:二分答案+线段树 首先我们知道,对于一个01序列排序,用线段树维护的话可以做到单次排序复杂度仅为log级别. 这道题只有一个询问,所以离线没有意义,而一个询问让我们很自然的想到二分答案.先二分 ...

  2. bzoj 4552 [Tjoi2016&Heoi2016]排序 (二分答案 线段树)

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=4552 题意: 给你一个1-n的全排列,m次操作,操作由两种:1.将[l,r]升序排序,2 ...

  3. BZOJ 4552 [Tjoi2016&Heoi2016]排序 | 二分答案 线段树

    题目链接 题面 题目描述 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题,需要你来帮助他.这个难题是这样子的:给出一个1到n的全排列,现在对这 ...

  4. 【BZOJ4552】【HEOI2016】排序 [二分答案][线段树]

    排序 Time Limit: 60 Sec  Memory Limit: 256 MB[Submit][Status][Discuss] Description 在2016年,佳媛姐姐喜欢上了数字序列 ...

  5. HDU 5649 DZY Loves Sorting(二分答案+线段树/线段树合并+线段树分割)

    题意 一个 \(1\) 到 \(n\) 的全排列,\(m\) 种操作,每次将一段区间 \([l,r]\) 按升序或降序排列,求 \(m\) 次操作后的第 \(k\) 位. \(1 \leq n \le ...

  6. [HEOI2016/TJOI2016] 排序 解题报告(二分答案/线段树分裂合并+set)

    题目链接: https://www.luogu.org/problemnew/show/P2824 题目描述: 在2016年,佳媛姐姐喜欢上了数字序列.因而他经常研究关于序列的一些奇奇怪怪的问题,现在 ...

  7. [BZOJ4552][Tjoi2016&Heoi2016]排序(二分答案+线段树)

    二分答案mid,将>=mid的设为1,<mid的设为0,这样排序就变成了区间修改的操作,维护一下区间和即可 然后询问第q个位置的值,为1说明>=mid,以上 时间复杂度O(nlog2 ...

  8. YbtOJ#463-序列划分【二分答案,线段树,dp】

    正题 题目链接:https://www.ybtoj.com.cn/problem/463 题目大意 给出长度为\(n\)的序列\(A,B\).要求划分成若干段满足 对于任何\(i<j\),若\( ...

  9. BZOJ_5343_[Ctsc2018]混合果汁_二分答案+主席树

    BZOJ_5343_[Ctsc2018]混合果汁_二分答案+主席树 题意:给出每个果汁的价格p,美味度d,最多能放的体积l.定义果汁混合后的美味度为果汁的美味度的最小值. m次询问,要求花费不大于g, ...

随机推荐

  1. Why malloc+memset is slower than calloc?

    https://stackoverflow.com/questions/2688466/why-mallocmemset-is-slower-than-calloc/ The short versio ...

  2. Linux下bash的快捷键

    Ctrl + A  :切换到命令行开始 Ctrl + E :切换到命令行末尾 Ctrl + L : 清屏,相当于clear Ctrl + U :清除剪切光标前的内容 Ctrl + K :剪切清除光标后 ...

  3. 2.安装VS Code

    1 打开网站 https://www.visualstudio.com/zh-hans/ 2. 安装 3.可以在程序目录命令行下 code .    用vscode 打开程序 4.下载插件 复制 ex ...

  4. Ubuntu16.04 hadoop 伪分布式 的文件配置

    首先需要完成java环境的配置,这里就省略了. 完成 hadoop 伪分布(pesudo distribution),只需配置下面 五 个文件即可: hadoop-env.sh core-site.x ...

  5. Linux下重要日志及查看方式

    1.Linux下重要日志文件介绍 /var/log/boot.log 该文件记录了系统在引导过程中发生的事件,就是Linux系统开机自检过程显示的信息,如图1所示: 图1 /var/log/boot. ...

  6. Ubuntu18 中文乱码 问题 解决

    之前租的服务器没有中文乱码的问题,最近重装了一下系统, 出现了中文乱码, 以下是解决方案: 输入locale查看当前的语言是否是中文 root@ubuntu:~# locale LANG=zh_CN. ...

  7. php微信红包算法

    微信红包算法.php /**生成红包的函数*/ function getRandMoney($totalMoney, $totalPeople=2, $miniMoney=1){ $randRemai ...

  8. tcl之list操作

  9. 解决Linux使用php命令 -base comment not found并安装composer

    获取php的安装目录 使用 find / -name php.ini 查看php的安装位置 /usr/local/php/lib/php.ini # cd 到/usr/local/php/lib/ph ...

  10. Android中级教程之Android应用程序的生命周期

    Android应用程序的生命周期图 在大部分情况下,每个Android应用都将运行在自己的Linux进程中.当这个应用的某些代码需要执行时,进程就会被创建,并且将保持运行,直到该进程不再需要,而系统需 ...