[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;
}