zoukankan      html  css  js  c++  java
  • [HEOI2016/TJOI2016]排序

    题目描述

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

    输入输出格式

    输入格式:

    输入数据的第一行为两个整数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

    输出格式:

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

    输入输出样例

    输入样例#1: 复制
    6 3
    1 6 2 5 3 4
    0 1 4
    1 3 6
    0 2 4
    3
    输出样例#1: 复制
    5

    说明

    河北省选2016第一天第二题。原题的时限为6s,但是洛谷上是1s,所以洛谷的数据中,对于30%的数据,有 n,m<=1000,对于100%的数据,有 n,m<=30000

    题解:

    传说中的二分+01线段树。

    题目中每次将某段区间按升序或降序排序,考虑暴力,如果我们每次都暴力排一遍序,那么每次就是nlogn的复杂度,显然是承受不了的。

    试想如果要我们排序的序列是一个01序列,那么如果是升序,我们就只要将所有的1放到最后面,如果是降序,我们就只要将所有的1放到最前面。这样的复杂度是logn的。

    二分一个答案,将序列中大于等于这个答案的数赋值为1,用01线段树模拟一遍所有的排序。

    如果最后查询的位置为1,那么就说明这个位置的数大于等于mid;如果最后查询的位置为0,那么就说明这个位置的数小于mid,就可以根据这个缩小答案范围。

     1 //Never forget why you start
     2 #include<iostream>
     3 #include<cstdio>
     4 #include<cstdlib>
     5 #include<cstring>
     6 #include<cmath>
     7 #include<algorithm>
     8 #define ll(x) (x<<1)
     9 #define rr(x) (x<<1|1)
    10 using namespace std;
    11 int n,a[100005],m,t1[100005],t2[100005],t3[100005],q,ans;
    12 void init(){
    13   int i;
    14   scanf("%d%d",&n,&m);
    15   for(i=1;i<=n;i++)scanf("%d",&a[i]);
    16   for(i=1;i<=m;i++){
    17     scanf("%d%d%d",&t1[i],&t2[i],&t3[i]);
    18   }
    19   scanf("%d",&q);
    20 }
    21 int sgm[400005],lazy[400005];
    22 void push_up(int root,int left,int right){
    23   sgm[root]=sgm[ll(root)]+sgm[rr(root)];
    24 }
    25 void build(int root,int left,int right){
    26   if(left==right){
    27     sgm[root]=(a[left]>=ans);
    28     return;
    29   }
    30   if(left>right)return;
    31   int mid=(left+right)>>1;
    32   build(ll(root),left,mid);
    33   build(rr(root),mid+1,right);
    34   push_up(root,left,right);
    35 }
    36 void push_down(int root,int left,int right){
    37   if(lazy[root]==-1)return;
    38   int mid=(left+right)>>1;
    39   sgm[ll(root)]=(mid-left+1)*lazy[root];
    40   sgm[rr(root)]=(right-mid)*lazy[root];
    41   lazy[ll(root)]=lazy[root];
    42   lazy[rr(root)]=lazy[root];
    43   lazy[root]=-1;
    44 }
    45 void insert(int root,int left,int right,int l,int r,int v){
    46   if(l<=left&&right<=r){
    47     sgm[root]=(right-left+1)*v;
    48     lazy[root]=v;
    49     return;
    50   }
    51   if(l>right||r<left)return;
    52   push_down(root,left,right);
    53   int mid=(left+right)>>1;
    54   if(l<=mid)insert(ll(root),left,mid,l,r,v);
    55   if(mid<r)insert(rr(root),mid+1,right,l,r,v);
    56   push_up(root,left,right);
    57 }
    58 int query(int root,int left,int right,int l,int r){
    59   if(l<=left&&right<=r){
    60     return sgm[root];
    61   }
    62   if(l>right||r<left)return 0;
    63   push_down(root,left,right);
    64   int mid=(left+right)>>1;
    65   return query(ll(root),left,mid,l,r)+query(rr(root),mid+1,right,l,r);
    66 }
    67 bool judge(){
    68   build(1,1,n);
    69   memset(lazy,-1,sizeof(lazy));
    70   for(int i=1;i<=m;i++){
    71     int l=t2[i],r=t3[i],tot1=query(1,1,n,l,r),tot0=(r-l+1)-tot1;//0的个数和1的个数
    72     if(t1[i]==0){//升序
    73       insert(1,1,n,l,l+tot0-1,0);
    74       insert(1,1,n,l+tot0,r,1);
    75     }
    76     else{
    77       insert(1,1,n,l,l+tot1-1,1);
    78       insert(1,1,n,l+tot1,r,0);
    79     }
    80   }
    81   if(query(1,1,n,q,q))return false;
    82   else return true;
    83 }
    84 int main(){
    85   init();
    86   int l=1,r=n,mid;
    87   while(l<=r){
    88     ans=(l+r)>>1;
    89     if(judge())r=ans-1;
    90     else mid=ans,l=ans+1;
    91   }
    92   printf("%d
    ",mid);
    93   return 0;
    94 }
  • 相关阅读:
    Debian8搭建LEMP环境
    ProjectManager Beta 7 项目管理器发布
    我的Linux软件集
    修改/home内子目录的名字
    Nginx配置特定二级域名
    Debian8 安装wordpress博客
    LinuxMint18使用单独分区作为Home挂载点
    LinuxMint18配置Grub2默认启动操作系统
    《失恋33天》从绝境中走出来的故事
    爱的世界很拥挤,写在读《爱,就这么简单》之后
  • 原文地址:https://www.cnblogs.com/huangdalaofighting/p/8284285.html
Copyright © 2011-2022 走看看