LOJ2055-「TJOI / HEOI2016」排序

LOJ2055-「TJOI / HEOI2016」排序

  题意:

    给出一个1-n的全排列,在给出m个操作,每次会将一个区间的数升序或降序排列,求最后位置q上的数是什么.(n<=1e5)

  题解:

    我们二分最后位置上的数,然后我们将比这个数小的数赋值为-1,比这个数大的数赋值为1,这个数赋值为0,再用一个支持区间赋值,区间求和的线段树来维护这个数列.对于每个区间,区间和代表的是1的个数减去-1的个数.然后通过维护0所在的位置,我们可以得出区间中-1和1的数量和.通过这两个值,我们可以求出区间中-1的数量和1的数量.然后如果要对这个区间升序排序就将这个区间的前段赋值为-1,将这个区间的后段赋值为1,中间赋值为0.如果降序排序反过来就可以了.最后求出位置q上的值,如果为0表示当前数就是答案,如果为-1表示答案比当前数小,如果为1表示答案比当前数大.复杂度O(m*logn*logn).

#include<cstdio>
const int N=1e5;
struct node{int l,r,val,tag;}a[N*4+10];
struct data{int l,r; bool v;}b[N+10];
int arr[N+10],pos,n,m,q;
void build_tree(int p,int l,int r,int v){
    a[p].l=l; a[p].r=r; a[p].tag=0;
    if(l==r){
        if(arr[l]==v) pos=l,a[p].val=0;
        else a[p].val=arr[l]<v?-1:1;
    }else{
        int mid=(l+r)/2; build_tree(p*2,l,mid,v); build_tree(p*2+1,mid+1,r,v);
        a[p].val=a[p*2].val+a[p*2+1].val;
    }
}
void push_down(int p){
    if(!a[p].tag) return;
    a[p*2].tag=a[p].tag; a[p*2].val=(a[p*2].r-a[p*2].l+1)*a[p].tag;
    a[p*2+1].tag=a[p].tag; a[p*2+1].val=(a[p*2+1].r-a[p*2+1].l+1)*a[p].tag; a[p].tag=0;
}
void change(int p,int l,int r,int v){
    if(l>r) return;
    if(a[p].l==l&&a[p].r==r){
        a[p].tag=v; a[p].val=(r-l+1)*v; return;
    }
    int mid=(a[p].l+a[p].r)/2; push_down(p);
    if(r<=mid) change(p*2,l,r,v); else if(l>mid) change(p*2+1,l,r,v);
    else change(p*2,l,mid,v),change(p*2+1,mid+1,r,v);
    a[p].val=a[p*2].val+a[p*2+1].val;
}
int query(int p,int l,int r){
    if(l>r) return 0;
    if(a[p].l==l&&a[p].r==r) return a[p].val;
    int mid=(a[p].l+a[p].r)/2; push_down(p);
    if(r<=mid) return query(p*2,l,r); else if(l>mid) return query(p*2+1,l,r);
    else return query(p*2,l,mid)+query(p*2+1,mid+1,r);
}
int check(int v){
    build_tree(1,1,n,v);
    for(int i=1;i<=m;++i){
        bool isin=pos>=b[i].l&&pos<=b[i].r;
        int v=query(1,b[i].l,b[i].r),num=b[i].r-b[i].l+1-isin;
        int ln=(num-v)/2,rn=(num+v)/2;
        if(!b[i].v){
            change(1,b[i].l,b[i].l+ln-1,-1); change(1,b[i].r-rn+1,b[i].r,1);
            if(isin) change(1,pos=b[i].l+ln,b[i].l+ln,0);
        }else{
            change(1,b[i].l,b[i].l+rn-1,1); change(1,b[i].r-ln+1,b[i].r,-1);
            if(isin) change(1,pos=b[i].l+rn,b[i].l+rn,0);
        }
    }
    return query(1,q,q);
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;++i) scanf("%d",&arr[i]);
    for(int i=1;i<=m;++i) scanf("%d%d%d",&b[i].v,&b[i].l,&b[i].r);
    int l=1,r=n; scanf("%d",&q);
    for(;l!=r;){
        int mid=(l+r)/2,v=check(mid);
        if(v>0) l=mid+1; else if(v<0) r=mid-1;
        else{
            printf("%d",mid); return 0;
        }
    }
    printf("%d",l); return 0;
}

 

posted @ 2017-09-09 15:13  jxcakak  阅读(368)  评论(0编辑  收藏  举报