zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    《算法图解》——第六章 广度有限搜索
    《算法图解》——第一章 算法简介
    《算法图解》——第二章 选择排序
    go-json处理的问题
    Go断言
    Go Example--格式化字符串
    Go Example--strings
    Go Example--组合函数
    Go Example--defer
    Go Example--panic
  • 原文地址:https://www.cnblogs.com/jxcakak/p/7498284.html
Copyright © 2011-2022 走看看