zoukankan      html  css  js  c++  java
  • BZOJ4552:[Tjoi2016&Heoi2016]排序

    4552: [Tjoi2016&Heoi2016]排序

    Time Limit: 60 Sec  Memory Limit: 256 MB
    Submit: 1058  Solved: 585
    [Submit][Status][Discuss]

    Description

    在2016年,佳媛姐姐喜欢上了数字序列。因而他经常研究关于序列的一些奇奇怪怪的问题,现在他在研究一个难题
    ,需要你来帮助他。这个难题是这样子的:给出一个1到n的全排列,现在对这个全排列序列进行m次局部排序,排
    序分为两种:1:(0,l,r)表示将区间[l,r]的数字升序排序2:(1,l,r)表示将区间[l,r]的数字降序排序最后询问第q
    位置上的数字。

    Input

    输入数据的第一行为两个整数n和m。n表示序列的长度,m表示局部排序的次数。1 <= n, m <= 10^5第二行为n个整
    数,表示1到n的一个全排列。接下来输入m行,每一行有三个整数op, l, r, op为0代表升序排序,op为1代表降序
    排序, l, r 表示排序的区间。最后输入一个整数q,q表示排序完之后询问的位置, 1 <= q <= n。1 <= n <= 10^5
    ,1 <= m <= 10^5

    Output

     输出数据仅有一行,一个整数,表示按照顺序将全部的部分排序结束后第q位置上的数字。

    Sample Input

    6 3
    1 6 2 5 3 4
    0 1 4
    1 3 6
    0 2 4
    3

    Sample Output

    5
    思路{
      首先模拟是不行的吧。。。。。。。
      怎么搞呢》》》》》》》23333
      易知那个数满足单调性(废话)
      那我们就赢该二分答案,二分什么呢》
      应当把序列分为01串,然后线段树维护一下,修改乱搞咯。最后比较当前位置与二分答案的大小关系即可。时间复杂度O(logn*(mlog(n)+n))
    }
    #include<map>
    #include<set>
    #include<list>
    #include<deque>
    #include<cmath>
    #include<queue>
    #include<stack>
    #include<vector>
    #include<cstdio>
    #include<complex>
    #include<cstring>
    #include<cstdlib>
    #include<iostream>
    #include<algorithm>
    #define ls (o<<1)
    #define rs ((o<<1)|1)
    #define maxx 100010
    #define RG register
    #define mid ((l+r)>>1)
    using namespace std;
    int tree[maxx*4],a[maxx],n,m,lazy[maxx*4];bool sub[maxx];int sum;
    struct ask{
      int l,r,t;
    }b[maxx];
    void build(int o,int l,int r){
      if(l==r){tree[o]=(sub[l]==1);return;}
      build(ls,l,mid),build(rs,mid+1,r);
      tree[o]=tree[ls]+tree[rs];
    }
    void down(int o,int l,int r){
      if(lazy[o]!=-1)tree[rs]=(r-mid)*lazy[o],tree[ls]=(mid-l+1)*lazy[o];
      if(lazy[o]!=-1)lazy[rs]=lazy[ls]=lazy[o];lazy[o]=-1;
    }
    void update(int o,int l,int r,int L,int R,int num){
      if(l!=r)down(o,l,r);
      if(l>=L&&r<=R){tree[o]=num*(r-l+1),lazy[o]=num;return;}
      if(mid<L)update(rs,mid+1,r,L,R,num);
      else if(mid>=R)update(ls,l,mid,L,R,num);
      else update(rs,mid+1,r,L,R,num),update(ls,l,mid,L,R,num);
      tree[o]=tree[ls]+tree[rs];
    }
    int query(int o,int l,int r,int L,int R){
      if(l!=r)down(o,l,r);
      if(l>=L&&r<=R)return tree[o];
      if(mid<L)return query(rs,mid+1,r,L,R);
      else if(mid>=R)return query(ls,l,mid,L,R);
      else return query(rs,mid+1,r,L,R)+query(ls,l,mid,L,R);
    }int pos;
    int main(){
      scanf("%d%d",&n,&m);int l=66666666,r=-666666666;
      for(int i=1;i<=n;++i)scanf("%d",&a[i]),l=min(l,a[i]),r=max(r,a[i]);
      for(int i=1;i<=m;++i)scanf("%d%d%d",&b[i].t,&b[i].l,&b[i].r);scanf("%d",&pos);
      while(l<=r){memset(lazy,-1,sizeof(lazy));
        for(RG int i=1;i<=n;++i)if(a[i]>mid)sub[i]=1;else sub[i]=0;
        build(1,1,n);
        for(RG int i=1;i<=m;++i){
          sum=query(1,1,n,b[i].l,b[i].r);
          if(b[i].t){
        if(sum)update(1,1,n,b[i].l,b[i].l+sum-1,1);
        if(sum!=b[i].r-b[i].l+1)update(1,1,n,b[i].l+sum,b[i].r,0);
          }
          else{
        if(sum)update(1,1,n,b[i].r-sum+1,b[i].r,1);
        if(sum!=b[i].r-b[i].l+1)update(1,1,n,b[i].l,b[i].r-sum,0);
          }
        }int axx=query(1,1,n,pos,pos);
        if(!axx)r=mid-1;else l=mid+1;
      }cout<<l;return 0;
    }
    
  • 相关阅读:
    给刚工作不久的程序猿同学的一封信
    Java进阶篇设计模式之六 ----- 组合模式和过滤器模式
    Java进阶篇设计模式之五-----外观模式和装饰器模式
    Java进阶篇设计模式之四 -----适配器模式和桥接模式
    Java进阶篇设计模式之三 ----- 建造者模式和原型模式
    SpringBoot简单打包部署(附工程)
    SSM框架——详细整合教程(Spring+SpringMVC+MyBatis)【转载】
    Eclipse快捷键大全(转载)
    在redis一致性hash(shard)中使用lua脚本的坑
    如何评价微软Connect 2015?[转载]
  • 原文地址:https://www.cnblogs.com/zzmmm/p/7141420.html
Copyright © 2011-2022 走看看