[bzoj4552]排序

[bzoj4552]排序


听说线段树合并nlogn来着。。。

考虑二分答案,将小于等于mid的数设为0,大于mid的设为1,于是可以nlogn模拟判定(没算二分的)

  • 代码
#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int a[N],n,m,P;
int opt[N],l[N],r[N];
struct segtree{
    int s[N*8],lzy[N*8];
    inline void pushdown(int x,int l,int r){
        if(lzy[x]==-1)return;
        s[x]=(r-l+1)*lzy[x];
        if(l!=r)lzy[x<<1]=lzy[x<<1|1]=lzy[x];
        lzy[x]=-1;
    }
    inline void pushup(int x,int l,int r){
        int mid=(l+r)>>1,lch=x<<1,rch=x<<1|1;
        if(l==r)return;
        pushdown(lch,l,mid);pushdown(rch,mid+1,r);
        lzy[x]=-1,s[x]=s[lch]+s[rch];
    }
    inline void build(int x,int l,int r,int sum){
        int mid=(l+r)>>1,lch=x<<1,rch=x<<1|1;
        lzy[x]=-1;
        if(l==r){
            s[x]=sum>=a[l]?0:1;
            return;
        }
        build(lch,l,mid,sum);build(rch,mid+1,r,sum);
        s[x]=s[lch]+s[rch];
    }
    inline void give(int x,int l,int r,int lx,int rx,int sum){
        int mid=(l+r)>>1,lch=x<<1,rch=x<<1|1;
        if(lx<=l&&r<=rx){
            lzy[x]=sum;
            return;
        }
        pushdown(x,l,r);
        if(lx<=mid)give(lch,l,mid,lx,rx,sum);
        if(rx>mid)give(rch,mid+1,r,lx,rx,sum);
        pushup(x,l,r);
    }
    inline int sum(int x,int l,int r,int lx,int rx){
        int mid=(l+r)>>1,lch=x<<1,rch=x<<1|1;
        pushdown(x,l,r);
        if(lx<=l&&rx>=r){
            return s[x];
        }
        if(rx<=mid)return sum(lch,l,mid,lx,rx);
        else if(lx>mid)return sum(rch,mid+1,r,lx,rx);
        return sum(lch,l,mid,lx,rx)+sum(rch,mid+1,r,lx,rx);
    }
}T;
 
inline bool chk(int s){
    T.build(1,1,n,s);
    for(int p=1;p<=m;p++){
        int o=opt[p],ql=l[p],qr=r[p];
        if(ql>qr)swap(ql,qr);
        int al=qr-ql+1;
        int one=T.sum(1,1,n,ql,qr);
        int zero=al-one;
        if(o==0){
            if(zero!=0)T.give(1,1,n,ql,ql+zero-1,0);
            if(one!=0)T.give(1,1,n,qr-one+1,qr,1);
        } else {
            if(one!=0)T.give(1,1,n,ql,ql+one-1,1);
            if(zero!=0)T.give(1,1,n,qr-zero+1,qr,0);
        }
    }
    int numb=T.sum(1,1,n,P,P);
    if(numb==1)return false;
    else return true;
}
 
int main()
{
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)scanf("%d",&a[i]);
    for(int i=1;i<=m;i++)scanf("%d%d%d",&opt[i],&l[i],&r[i]);
    scanf("%d",&P);
    int l=1,r=n;
    while(l<r){
        int mid=(l+r)>>1;
        bool res=chk(mid);
        if(res)r=mid;
        else l=mid+1;
    }
    printf("%d\n",l);
}

猜你喜欢

转载自blog.csdn.net/qq_35923186/article/details/82807661