[HEOI2016/TJOI2016]排序

[HEOI2016/TJOI2016]排序

考虑二分答案,那么每次就要求出第\(p\)位上的数字大还是小。

考虑直接变换\(01\)来进行排序操作,那么直接用一个区间赋值,区间查询即可。

二分后通过\(while\)保证答案正确。

// Problem: P2824 [HEOI2016/TJOI2016]排序
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/P2824
// Memory Limit: 256 MB
// Time Limit: 4000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long 
#define N 100005

ll t[N << 2],num[N],tag[N];//维护1的数量

#define ls(x) (x << 1)
#define rs(x) (x << 1 | 1)
#define mid ((l + r) >> 1)

ll n,m,p;

struct P{
	ll l,r,opt;
}q[N];


inline void up(int u){
	t[u] = t[ls(u)] + t[rs(u)];
}

inline void build(int u,int l,int r,int x){
	if(l == r){
		t[u] = num[l] >= x;
		return;
	}
	build(ls(u),l,mid,x);
	build(rs(u),mid + 1,r,x);
	up(u);
}

inline void del(int u,int len){
	if(tag[u] == 1){
		t[u] = 0;
		return;
	}
	if(tag[u] == 2){
		t[u] = len;
		return ;
	}
}

inline void down(int u,int l,int r){
	if(tag[u]){
		tag[ls(u)] = tag[u];
		tag[rs(u)] = tag[u];
		del(ls(u),mid - l + 1);
		del(rs(u),r - mid);
		tag[u] = 0;
	}
}

inline void change(int u,int l,int r,int tl,int tr,int to){
	if(tl > tr)
	return;
	if(tl <= l && r <= tr){
		tag[u] = to;
		del(u,r - l + 1);
		return;
	}
	down(u,l,r);
	if(tl <= mid)
	change(ls(u),l,mid,tl,tr,to);
	if(tr > mid)
	change(rs(u),mid + 1,r,tl,tr,to);
	up(u);
	return;
}

inline ll que(int u,int l,int r,int tl,int tr){
	if(tl <= l && r <= tr)
		return t[u];
	ll ans = 0;
	down(u,l,r);
	if(tl <= mid)
	ans += que(ls(u),l,mid,tl,tr);
	if(tr > mid)
	ans += que(rs(u),mid + 1,r,tl,tr);
	return ans;
}

//1 2 5 6 3 4
//1 2 6 5 4 3
//1 2 5 

inline bool check(int x){
	std::memset(tag,0,sizeof(tag));
	std::memset(t,0,sizeof(t));
	build(1,1,n,x);
	for(int i = 1;i <= m;++i){
		ll cnt = que(1,1,n,q[i].l,q[i].r);
		if(q[i].opt == 1){//降序
			change(1,1,n,q[i].l,q[i].l + cnt - 1,2);//1
			change(1,1,n,q[i].l + cnt,q[i].r,1);
		}else{
			cnt = q[i].r - q[i].l + 1 - cnt;
			change(1,1,n,q[i].l,q[i].l + cnt - 1,1);//1
			change(1,1,n,q[i].l + cnt,q[i].r,2);			
		}
	}
	return que(1,1,n,p,p);
}

int main(){
	scanf("%lld%lld",&n,&m);
	for(int i = 1;i <= n;++i)
	scanf("%lld",&num[i]);
	for(int i = 1;i <= m;++i)
	scanf("%lld%lld%lld",&q[i].opt,&q[i].l,&q[i].r);
	scanf("%lld",&p);
	ll l = 1,r = n;
	ll ans = 0;
	while(l + 1 <= r){
		if(check(mid))
			ans = mid,l = mid + 1;
		else
			r = mid - 1;
	}
	while(check(ans + 1))
	ans = ans + 1;
	std::cout<<ans<<std::endl;
}
posted @ 2021-07-29 14:13  fhq_treap  阅读(39)  评论(0编辑  收藏  举报