• JZOJ 1386. 排序


    题目

    Description

      你收到一项对数组进行排序的任务,数组中是1到N个一个排列。你突然想出以下一种特别的排序方法,分为以下N个阶段:
      •阶段1,把数字1通过每次交换相邻两个数移到位置1;
      •阶段2,用同样的方法把N移到位置N;
      •阶段3,把数字2移到位置2处;
      •阶段4,把数字N-1移到位置N-1处;
      •依此类推。
      换句话说,如果当前阶段为奇数,则把最小的未操作的数移到正确位置上,如果阶段为偶数,则把最大的未操作的数移到正确位置上。
      写一个程序,给出初始的排列情况,计算每一阶段交换的次数。
     

    Input

      第一行包含一个整数N(1<=N<=100000),表示数组中元素的个数。
      接下来N行每行一个整数描述初始的排列情况。

    Output

      输出每一阶段的交换次数。
     

    Sample Input

    输入1:
    3
    2
    1
    3
    
    
    输入2:
    5
    5
    4
    3
    2
    1
    
    输出3:
    7
    5
    4
    3
    7
    1
    2
    6
    

    Sample Output

    输出1:
    1
    0
    0
    
    输出2:
    4
    3
    2
    1
    0
    
    输出3:
    4
    2
    3
    0
    2
    1
    0
    
     

    Data Constraint

     
     

    Hint

    【数据范围】
      70%的数据N<=100

    分析

     

    • 刚开始是想用差分数值纪录移动的差值
    • 但是这不能直接一个区间直接加
    • 因为影响向右的数就要减或加所以要n
    • 我们认真思考,答案其实不就是前面或后面还未移动的个数
    • 向前移动的就数前面的,不然数后面
    • 线段树区间查询,单点修改

    代码

     1 #include<iostream>
     2 using namespace std;
     3 int a[100001],to[100001],bj[100001];
     4 struct sb
     5 {
     6     int l,r,w;
     7 }t[100001*4];
     8 void build(int k,int a,int b)
     9 {
    10     t[k].l=a; t[k].r=b;
    11     if (a==b) {
    12         t[k].w=1;
    13         return;
    14     }
    15     int mid=a+b>>1;
    16     build(k<<1,a,mid);
    17     build(k<<1|1,mid+1,b);
    18     t[k].w=t[k<<1].w+t[k<<1|1].w;
    19 }
    20 int check(int x,int y,int k)
    21 {
    22     if (t[k].l==x&&t[k].r==y)
    23         return t[k].w;
    24     int mid=(t[k].l+t[k].r)/2;
    25     if (y<=mid) return check(x,y,k*2);
    26     else if (x>mid) return check(x,y,k*2+1);
    27     else
    28         return check(x,mid,k*2)+check(mid+1,y,k*2+1);
    29 }
    30 void change(int k,int mb)
    31 {
    32     if (t[k].l<=mb&&t[k].r>=mb)
    33         t[k].w--;
    34     if (t[k].l==t[k].r) return;
    35     int mid=t[k].l+t[k].r>>1;
    36     if (mb<=mid) change(k<<1,mb);
    37     else change(k<<1|1,mb);
    38 }
    39 int main ()
    40 {
    41     int n;
    42     cin>>n;
    43     for (int i=1;i<=n;i++) cin>>a[i],to[a[i]]=i;
    44     build(1,1,n);
    45     int tot=0,i=1,j=n;
    46     while (++tot<=n)
    47     {
    48         if (tot%2==1)
    49         {
    50             int wz=to[i],ans=check(1,wz,1)-1;
    51             if (ans<0) ans=0;
    52             cout<<ans<<endl;
    53             change(1,wz);
    54             i++;
    55         }
    56         else
    57         {
    58             int wz=to[j],ans=check(wz,n,1)-1;
    59             if (ans<0) ans=0;
    60             cout<<ans<<endl;
    61             change(1,wz);
    62             j--;
    63         }
    64     }
    65 }
    为何要逼自己长大,去闯不该闯的荒唐
  • 相关阅读:
    Flume(二)Flume的Source类型
    Hadoop(四)HDFS的高级API操作
    Flume(一)Flume的基础介绍与安装
    MySQL 的索引优化
    CentOS7.5安装Mysql5.7.22
    Hadoop(三)HDFS读写原理与shell命令
    iOS NSDictionary JSON 相互转换
    iOS UICollectionView 在滚动时停在某个item位置上
    vim的基本使用方法
    初次使用git上传代码到github远程仓库
  • 原文地址:https://www.cnblogs.com/zjzjzj/p/11318872.html
Copyright © 2020-2023  润新知