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

 

posted @ 2019-12-12 19:59  wlzs1432  阅读(174)  评论(0编辑  收藏  举报