P2824 [HEOI2016/TJOI2016]排序

题目:P2824 [HEOI2016/TJOI2016]排序

思路:

线段树专题讲的。
讲过不只一次了,方法挺巧妙的。

这道题并不是真的需要使用线段树来做排序。
• 考虑这道题的特殊性质,发现我们只需要求最后一个元素的大小。
• 由于是全排列,我们可以直接二分答案x,将排列中大于等于x的标记为1,小于x的元素标记为0,维护一颗支持区间覆盖、查询区间和的线段树。每次排序时,查询区间中0、1的个数,之后若是升序排列将前面一段覆盖成0、后一段覆盖成1,降序排列则是反过来。
• 完成操作后,只需查询所需位置的权值即可完成二分的检验工作,总
复杂度O(nlog2n)

在线算法先咕着,以后再填。


Code:

#include <bits/stdc++.h>
using namespace std;
const int N=2e5+5;
int n,m,pos,a[N],b[N];
struct data{
	int type,l,r;
}q[N];
struct Tree{
	int l,r,sum,tag;
#define l(p) (node[p].l)
#define r(p) (node[p].r)
#define sum(p) (node[p].sum)
#define tag(p) (node[p].tag)
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
}node[N<<2];
void build(int p,int l,int r){
	l(p)=l;r(p)=r;tag(p)=-1;
	if(l==r) return (void) (sum(p)=b[l]);
	int mid=(l(p)+r(p))>>1;
	build(ls(p),l,mid);
	build(rs(p),mid+1,r);
	sum(p)=sum(ls(p))+sum(rs(p));
}
void upd(int p,int v){
	tag(p)=v;
	sum(p)=(r(p)-l(p)+1)*v;
}
void pdown(int p){
	if(tag(p)!=-1){
		upd(ls(p),tag(p));
		upd(rs(p),tag(p));
		tag(p)=-1;
	}
}
int query(int p,int L,int R){
	if(l(p)>R||r(p)<L) return 0;
	if(L<=l(p)&&r(p)<=R) return sum(p);
	pdown(p);
	return query(ls(p),L,R)+query(rs(p),L,R);
}
void Set(int p,int L,int R,int v){
	if(l(p)>R||r(p)<L) return;
	if(L<=l(p)&&r(p)<=R) return upd(p,v);
	pdown(p);
	Set(ls(p),L,R,v);
	Set(rs(p),L,R,v);
	sum(p)=sum(ls(p))+sum(rs(p));
}
bool check(int mid){
	for(int i=1;i<=n;++i) b[i]=(a[i]>=mid);
	build(1,1,n);
	for(int i=1;i<=m;++i){
		int cnt=query(1,q[i].l,q[i].r);
		int len=q[i].r-q[i].l+1;
		if(q[i].type==0) Set(1,q[i].l,q[i].l+len-cnt-1,0),Set(1,q[i].l+len-cnt,q[i].r,1);
		else Set(1,q[i].l,q[i].l+cnt-1,1),Set(1,q[i].l+cnt,q[i].r,0);
	}
	return query(1,pos,pos); 
}
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);
	scanf("%d",&pos);
	int l=1,r=n,ans=1;
	while(l<=r){
		int mid=(l+r)>>1;
		if(check(mid)) ans=max(ans,mid),l=mid+1;
		else r=mid-1;
	}
	printf("%d\n",ans);
	return 0;
}
posted @   宇興  阅读(183)  评论(0编辑  收藏  举报
编辑推荐:
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示