• 洛谷 2824 [HEOI2016/TJOI2016]排序


    【题意概述】

      对一个1到n的排列做m次区间排序,最后询问位置q上面的数。

    【题解】

      区间排序的效率是nlogn,所以暴力做的话效率是mnlogn,显然达不到要求。

      我们考虑二分答案。如果某个位置的数比mid小,就设为0,如果么某个位置的数大于等于mid,就设为1.  check的时候我们只需对01序列排序就好了,这个可以用线段树做到logn.

      如果排序后位置q的数为1,那么就表示原来这里的数大于等于mid,所以我们要挪动l,否则挪动r.

      总的时间复杂度为m*logn*logn

     1 #include<cstdio>
     2 #include<cstring>
     3 #include<algorithm>
     4 #define LL long long
     5 #define rg register
     6 #define N 30010
     7 #define ls (u<<1)
     8 #define rs (u<<1|1)
     9 #define len(x) (a[x].r-a[x].l+1)
    10 using namespace std;
    11 int n,m,v[N],l,r,mid,pos;
    12 struct tree{
    13     int l,r,c0,c1,num; bool same;
    14 }a[N<<2];
    15 struct opt{
    16     int l,r,type;
    17 }b[N];
    18 inline int read(){
    19     int k=0,f=1; char c=getchar();
    20     while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
    21     while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
    22     return k*f;
    23 }
    24 void build(int u,int l,int r){
    25     a[u].l=l; a[u].r=r; a[u].same=0; a[u].c0=a[u].c1=0;
    26     if(l<r){
    27         int mid=(l+r)>>1;
    28         build(ls,l,mid); build(rs,mid+1,r); 
    29         a[u].c0=a[ls].c0+a[rs].c0; a[u].c1=a[ls].c1+a[rs].c1;
    30     }
    31     else{
    32         if(v[l]>=mid) a[u].c1=1,a[u].c0=0;
    33         else a[u].c0=1,a[u].c1=0;
    34     }
    35 }
    36 inline void pushdown(int u){
    37     a[u].same=0; a[ls].same=a[rs].same=1;
    38     a[ls].num=a[rs].num=a[u].num;
    39     if(!a[u].num) a[ls].c0=len(ls),a[ls].c1=0,a[rs].c0=len(rs),a[rs].c1=0;
    40     else a[ls].c0=0,a[ls].c1=len(ls),a[rs].c0=0,a[rs].c1=len(rs);
    41 }
    42 void update(int u,int l,int r,int num){
    43     if(l<=a[u].l&&a[u].r<=r){
    44         a[u].same=1; a[u].num=num;
    45         if(num==1) a[u].c1=len(u),a[u].c0=0;
    46         else a[u].c0=len(u),a[u].c1=0;
    47         return;
    48     }
    49     if(a[u].same) pushdown(u);
    50     int mid=(a[u].l+a[u].r)>>1;
    51     if(l<=mid) update(ls,l,r,num);
    52     if(r>mid) update(rs,l,r,num);
    53     a[u].c0=a[ls].c0+a[rs].c0;
    54     a[u].c1=a[ls].c1+a[rs].c1;
    55 }
    56 int query0(int u,int l,int r){
    57     if(l<=a[u].l&&a[u].r<=r) return a[u].c0;
    58     if(a[u].same) pushdown(u);
    59     int mid=(a[u].l+a[u].r)>>1,ret=0;
    60     if(l<=mid) ret=query0(ls,l,r);
    61     if(r>mid) ret+=query0(rs,l,r);
    62     return ret; 
    63 }
    64 int query1(int u,int l,int r){
    65     if(l<=a[u].l&&a[u].r<=r) return a[u].c1;
    66     if(a[u].same) pushdown(u);
    67     int mid=(a[u].l+a[u].r)>>1,ret=0;
    68     if(l<=mid) ret=query1(ls,l,r);
    69     if(r>mid) ret+=query1(rs,l,r);
    70     return ret; 
    71 }
    72 inline bool check(){
    73     build(1,1,n); int r0=0,r1=0;
    74     for(rg int i=1;i<=m;i++){
    75         r0=query0(1,b[i].l,b[i].r); r1=query1(1,b[i].l,b[i].r);
    76         if(b[i].type==0) update(1,b[i].l,b[i].l+r0-1,0),update(1,b[i].l+r0,b[i].r,1);
    77         else update(1,b[i].l,b[i].l+r1-1,1),update(1,b[i].l+r1,b[i].r,0);
    78     }
    79     r0=query0(1,pos,pos); r1=query1(1,pos,pos);
    80     return r1>0;
    81 }
    82 int main(){
    83     n=read(); m=read();
    84     for(rg int i=1;i<=n;i++) v[i]=read();
    85     for(rg int i=1;i<=m;i++) b[i].type=read(),b[i].l=read(),b[i].r=read();
    86     pos=read();
    87     l=1,r=n+1;
    88     while(l+1<r){
    89         mid=(l+r)>>1;
    90         if(check()) l=mid; else r=mid;
    91     }
    92     printf("%d
    ",l);
    93 }
    View Code
  • 相关阅读:
    每一次面试都是提升(一)
    Gof设计模式分组
    MSSqlServer 通过sql语句 还原数据库(已有备份文件)
    自定义配置节与配置节的读取
    Javascript判断时间大小的方法
    C#微信开发之旅(十三):V2订单查询&退款(完结)
    C#微信开发之旅(十二):V2告警接口&维权接口
    C#微信开发之旅(十一):V2发货接口
    C#微信开发之旅(十):APP预支付及支付参数生成(V2)
    C#微信开发之旅(九):JSAPI支付(V3)
  • 原文地址:https://www.cnblogs.com/DriverLao/p/9528353.html
Copyright © 2020-2023  润新知