LuoguP2824 [HEOI2016/TJOI2016]排序
LuoguP2824 [HEOI2016/TJOI2016]排序
题目
题解
考虑对一个0,1区间排序,显然线段树可以很容易做到
现在我们询问第Q个位置的值:我们可以考虑二分答案,将大于Q的答案设为1,将小于Q的答案设为0
显然当当前二分答案的值大于实际值,第Q个位置的值一定为1,所以可以二分
#include<bits/stdc++.h> using namespace std; #define ll long long #define re register inline ll read() { ll f = 1,x = 0; char ch; do { ch = getchar(); if(ch == '-') f = -1; }while(ch<'0'||ch>'9'); do { x = (x<<3) + (x<<1) + ch - '0'; ch = getchar(); }while(ch>='0'&&ch<='9'); return f*x; } const int MAXN = 1e5 + 10; #define lc o<<1 #define rc o<<1|1 int n,m,q; int a[MAXN]; int ans; int add[MAXN<<2],sum[MAXN<<2]; int opt[MAXN],l[MAXN],r[MAXN]; inline void build(int o,int l,int r,int v) { if(l == r) { sum[o] = (a[l]>=v);add[o]=0;return; } int mid = (l+r)>>1; build(lc,l,mid,v); build(rc,mid+1,r,v); sum[o]=sum[lc]+sum[rc];add[o]=0; } inline void pushdown(int o,int l,int r) { if(!add[o]) return; int mid = (l+r)>>1; add[lc]=add[rc]=add[o]; if(add[o]==1) { sum[lc]=mid-l+1; sum[rc]=r-mid; } else { sum[lc]=sum[rc]=0; } add[o]=0; } inline void update(int o,int l,int r,int x,int y,int v) { if(x<=l&&y>=r) { sum[o]=v*(r-l+1); if(v==1) add[o]=1; else add[o]=-1; return; } if(l>y||x>r) return; pushdown(o,l,r); int mid = (l+r)>>1; update(lc,l,mid,x,y,v); update(rc,mid+1,r,x,y,v); sum[o]=sum[lc]+sum[rc]; } inline int query(int o,int l,int r,int x,int y) { if(x<=l&&y>=r) return sum[o]; if(l>y||r<x) return 0; int mid = (l+r)>>1; pushdown(o,l,r); return query(lc,l,mid,x,y)+query(rc,mid+1,r,x,y); } inline int query2(int o,int l,int r,int p) { if(l==r&&l==p) return sum[o]; int mid = (l+r)>>1; pushdown(o,l,r); if(mid>=p) return query2(lc,l,mid,p); return query2(rc,mid+1,r,p); } inline bool check(int x) { build(1,1,n,x); for(int i=1;i<=m;i++) { int res = query(1,1,n,l[i],r[i]); if(opt[i]==0) { update(1,1,n,r[i]-res+1,r[i],1); update(1,1,n,l[i],r[i]-res,0); } else { update(1,1,n,l[i]+res,r[i],0); update(1,1,n,l[i],l[i]+res-1,1); } } return query2(1,1,n,q); } int main() { n = read(),m = read(); for(int i=1;i<=n;i++) a[i] = read(); for(int i=1;i<=m;i++) opt[i]=read(),l[i]=read(),r[i]=read(); q=read(); int l = 1,r = n; while(l <= r) { int mid = (l + r) >> 1; if(check(mid)) { //cout << mid << endl; ans = mid; l = mid + 1; } else r = mid - 1; } cout << ans << endl; }