[HEOI2016/TJOI2016] 排序 题解

这题其实就是一个 thick 题,知道这个 thick 其实就是大水体了。

像这样的区间排序题,直接排序肯定不行,但是我们发现 01 数组排序很快,可以用线段树来实现 \(O(\log n)\) 的排序时间复杂度,就是区间赋值。

对大于等于这个值的都赋值为 1,其他为 0,若最后 \(a_q=1\) 就是可行的。

发现答案有单调性,直接二分即可。

#include<bits/stdc++.h>
#pragma GCC optimize(3)
#pragma GCC optimize("inline")
#pragma GCC target("avx", "sse2")
#pragma GCC optimize("unroll-loops")
using namespace std;
const int N=1e5+5;
int n,m,a[N];
int l[N],r[N],opt[N],X;
struct SEG {
#define ls p<<1
#define rs p<<1|1
	int c[N<<2],tag[N<<2],len[N<<2];
	void pushup(int p) {
		c[p]=c[ls]+c[rs];
	}
	void pushdown(int p) {
		if(tag[p]!=-1) {
			tag[ls]=tag[p];
			tag[rs]=tag[p];
			c[ls]= tag[p]*len[ls];
			c[rs]= tag[p]*len[rs];
			tag[p]=-1;
		}
	}
	void build(int p,int l,int r,int &x) {
		tag[p]=-1;
		len[p]=r-l+1;
		if(l==r)return void (c[p]=(a[l]>=x));
		int mid=l+r>>1;
		build(ls,l,mid,x),build(rs,mid+1,r,x);
		pushup(p);
	}
	void change(int p,int l,int r,int L,int R,int x) {
		if(L<=l&&r<=R) {
			c[p]=x*len[p];
			tag[p]=x;
			return ;
		}
		int mid=l+r>>1;
		pushdown(p);
		if(L<=mid)change(ls,l,mid,L,R,x);
		if(R> mid)change(rs,mid+1,r,L,R,x);
		pushup(p);
	}
	int query(int p,int l,int r,int L,int R) {
		if(L<=l&&r<=R) return c[p];
		int mid=l+r>>1,res=0;
		pushdown(p);
		if(L<=mid) res+=query(ls,l,mid,L,R);
		if(R> mid) res+=query(rs,mid+1,r,L,R);
		return res;
	}
} seg;
bool check(int mid) {
	seg.build(1,1,n,mid);
	//cout<<mid<<endl<<endl;
	for(int i=1; i<=m; i++) {
		int x=seg.query(1,1,n,l[i],r[i]);
		if(x==r[i]-l[i]+1 ||!x)continue;
		//cout<<x<<" "<<opt[i]<<endl;
		if(opt[i]) {
			seg.change(1,1,n,l[i],l[i]+x-1,1);
			seg.change(1,1,n,l[i]+x,r[i],0);
		}
		else {
			seg.change(1,1,n,l[i],(r[i]-x),0);
			seg.change(1,1,n,(r[i]-x)+1,r[i],1);
		}
	}
	//cout<<seg.query(1,1,n,X,X)<<endl;
	return seg.query(1,1,n,X,X);
}
signed 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",&opt[i],&l[i],&r[i]);
	int l=1,r=n,ans=0;
	scanf("%d",&X);
	while(l<=r) {
		int mid=l+r>>1;
		if(check(mid))
			ans=mid,l=mid+1;
		else r=mid-1;
	}
	printf("%d",ans);
	return 0;
}

posted @ 2025-05-15 17:29  hnczy  阅读(18)  评论(0)    收藏  举报