1. 程式人生 > >[BZOJ] 4552: [Tjoi2016&Heoi2016]排序

[BZOJ] 4552: [Tjoi2016&Heoi2016]排序

通過各種手段把序列問題變成01序列問題可以簡化問題

這裡可以用二分答案,把大於等於的變成1,小於的變成0

然後區間排序就是線段樹區間賦值操作啦

複雜度\(O(nlog^2n)\)

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>

using namespace std;

inline int rd(){
    int ret=0,f=1;char c;
    while(c=getchar(),!isdigit(c))f=c=='-'?-1:1;
    while(isdigit(c))ret=ret*10+c-'0',c=getchar();
    return ret*f;
}
#define pc putchar
#define space() pc(' ')
#define nextline() pc('\n')
void pot(int x){if(!x)return;pot(x/10);pc('0'+x%10);}
void out(int x){if(!x)pc('0');if(x<0)pc('-'),x=-x;pot(x);}

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

const int MAXN = 100005;

int val[MAXN<<2],tag[MAXN<<2];

int n,m;
int a[MAXN];
int M;

void pushdown(int cur,int l,int r){
    if(tag[cur]==-1) return;
    if(l==r) return;
    val[ls]=(mid-l+1)*tag[cur];
    val[rs]=(r-mid)*tag[cur];
    tag[ls]=tag[cur];
    tag[rs]=tag[cur];
    tag[cur]=-1;
}

void pushup(int cur){val[cur]=val[ls]+val[rs];}

void build(int cur,int l,int r){
    if(l==r){val[cur]=(a[l]>=M);return;}
    build(ls,l,mid);build(rs,mid+1,r);
    pushup(cur);
}

void update(int L,int R,int cur,int l,int r,int w){
    if(L>R) return;
    if(L<=l&&r<=R){tag[cur]=w;val[cur]=w*(r-l+1);return;}
    pushdown(cur,l,r);
    if(L<=mid) update(L,R,ls,l,mid,w);
    if(mid <R) update(L,R,rs,mid+1,r,w);
    pushup(cur);
}

int query1(int L,int R,int cur,int l,int r){
    if(L<=l&&r<=R){return val[cur];}
    pushdown(cur,l,r);
    int ret=0;
    if(L<=mid) ret+=query1(L,R,ls,l,mid);
    if(mid <R) ret+=query1(L,R,rs,mid+1,r);
    return ret; 
}
struct Qry{
    int op,x,y; 
    Qry(int _x=0,int _y=0,int _z=0){op=_x;x=_y;y=_z;}
}qry[MAXN];

void clear(){
    memset(tag,-1,sizeof(tag));
    memset(val,0,sizeof(val));
}
    
int p;
bool check(){
    clear();    
    build(1,1,n);
    for(int i=1;i<=m;i++){
        int x=qry[i].x,y=qry[i].y;
        if(qry[i].op==1){
            int tmp=query1(x,y,1,1,n);
            update(x,x+tmp-1,1,1,n,1);
            update(x+tmp,y,1,1,n,0);
        }else{
            int tmp=y-x+1-query1(x,y,1,1,n);
            update(x,x+tmp-1,1,1,n,0);
            update(x+tmp,y,1,1,n,1);
        }
    }   
    return query1(p,p,1,1,n);
}   


int main(){
    n=rd();m=rd();
    for(int i=1;i<=n;i++) a[i]=rd();
    int tp,x,y;
    for(int i=1;i<=m;i++){
        tp=rd();x=rd();y=rd();
        qry[i]=Qry(tp,x,y);
    }
    p=rd();
    int l=1,r=n,ans=0;
    while(l<=r){
        M=(l+r)>>1;
        if(check()) l=M+1,ans=M;
        else r=M-1;
    }
    cout<<ans;
    return 0;
}