*题解:P2824 [HEOI2016/TJOI2016] 排序

原题链接

解析

“这个题不是典爆了,,,只跟大小相关的题想不到 0/1 Trick 建议先多做题。”

收到。

二分答案 \(x\),将大于等于 \(x\) 的数都标记为 \(1\),小于 \(x\) 的数都标记为 \(0\)。这样排序操作就变成了对 \(0/1\) 串排序,而这个操作相当于统计区间 \(1\) 个数和区间赋值,可以用线段树来维护。最终答案就为使得所有操作过后位置 \(q\) 上的数为 \(1\) 的最小 \(x\)

时间复杂度 \(O(m\log^2n)\)

代码

#include <bits/stdc++.h>
#define ls(x) ((x) << 1)
#define rs(x) (((x) << 1) | 1)
#define mid ((l + r) >> 1)
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 1e5 + 5,M = 2e5 + 5,mod = 998244353;
int a[N],b[N];
int cnt1[N << 2],tag[N << 2];
int pos;
struct Query{
	int op,l,r;
}q[N];
int n,m;
void push_up(int p){
	cnt1[p] = cnt1[ls(p)] + cnt1[rs(p)];
}
void build(int p,int l,int r){
	tag[p] = -1;
	if(l == r){
		cnt1[p] = b[l];
		return;
	}
	build(ls(p),l,mid),build(rs(p),mid + 1,r);
	push_up(p);
}
void add_tag(int p,int l,int r,int k){
	tag[p] = k;
	cnt1[p] = (r - l + 1) * k;
}
void push_down(int p,int l,int r){
	if(tag[p] == -1) return;
	add_tag(ls(p),l,mid,tag[p]);
	add_tag(rs(p),mid + 1,r,tag[p]); 
	tag[p] = -1;
}
void modi(int p,int l,int r,int L,int R,int k){
	if(l > R || r < L) return;
	if(l >= L && r <= R){
		add_tag(p,l,r,k);
		return;
	}
	push_down(p,l,r);
	modi(ls(p),l,mid,L,R,k),modi(rs(p),mid + 1,r,L,R,k);
	push_up(p);
}
int ask(int p,int l,int r,int L,int R){
	if(l > R || r < L) return 0;
	if(l >= L && r <= R){
		return cnt1[p];
	}
	push_down(p,l,r);
	return ask(ls(p),l,mid,L,R) + ask(rs(p),mid + 1,r,L,R);
}

bool chk(int x){
	for(int i=1;i<=n;i++){
		b[i] = a[i] >= x;
	}	
	build(1,1,n);
	for(int i=1;i<=m;i++){
		int l = q[i].l,r = q[i].r;
		int x = ask(1,1,n,l,r);
		if(q[i].op == 0){
			modi(1,1,n,l,r - x,0);
			modi(1,1,n,r - x + 1,r,1);
		}else{
			modi(1,1,n,l,l + x - 1,1);
			modi(1,1,n,l + x,r,0);
		}
	}
	return ask(1,1,n,pos,pos);
}
int main(){
	ios::sync_with_stdio(false);
	cin.tie(0);
	cin>>n>>m;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=m;i++){
		cin>>q[i].op>>q[i].l>>q[i].r;
	}	
	cin>>pos;
	int l = 1,r = n;
	while(l < r){
		int md = (l + r + 1) >> 1;
		if(chk(md)){
			l = md;
		}else{
			r = md - 1;
		}
	}
	cout<<l;
	return 0;
}
posted @ 2025-11-08 16:59  yutar  阅读(10)  评论(0)    收藏  举报