zoukankan      html  css  js  c++  java
  • 洛谷 P4378 [USACO18OPEN]Out of Sorts S(树状数组求冒泡排序循环次数)

    传送门:Problem P4378

     https://www.cnblogs.com/violet-acmer/p/9833502.html

      要回宿舍休息了,题解明天再补吧。

    题解:

      定义一数组 a[maxn]
      考察冒泡排序的本质。

      冒泡排序,每次会把最大的数直接沉底,但是比较小的数,会往前面缓慢冒泡。

      具体来说,如果一个数 val 在数组有序后的排名是 i ,但是目前位置在 i 之后,那么,每次循环,val 必然会往前面移动一位。

    因为前面必然会有一个比 val 大的数往后沉。

      swap的次数,就是逆序对数

      循环的次数,就是max( i 前比a[i]大的数的个数)(i=1,2,3,......,n)

      注意事项:

      (1):首先需要做的是离散化原数组,因为 a[i] 的值最大可达 1e9,但 n 最大才 1e5,注意在排序的时候,对于值相同的两个数,初始编号小的在前。

      (2):最终结果要额外 +1

    AC代码:

     1 #include<iostream>
     2 #include<algorithm>
     3 #include<cstdio>
     4 using namespace std;
     5 #define lowbit(x) (x&(-x))
     6 const int maxn=1e5+50;
     7 
     8 int N;
     9 struct Node
    10 {
    11     int val;
    12     int id;//存储初始编号
    13     int newVal;//存储离散化后 val 对应的新值
    14 }a[maxn];
    15 //==============BIT===================
    16 int bit[maxn];
    17 void Add(int x)
    18 {
    19     while(x <= N)
    20     {
    21         bit[x]++;
    22         x += lowbit(x);
    23     }
    24 }
    25 int Sum(int x)
    26 {
    27     int sum=0;
    28     while(x > 0)
    29     {
    30         sum += bit[x];
    31         x -= lowbit(x);
    32     }
    33     return sum;
    34 }
    35 //=====================================
    36 bool cmp(Node _a,Node _b){
    37     //值不同,值小的在前;值相同,初始编号小的在前,保证排序的稳定性
    38     return _a.val < _b.val || (_a.val == _b.val && _a.id < _b.id);
    39 }
    40 bool cmp1(Node _a,Node _b){
    41     return _a.id < _b.id;
    42 }
    43 void Solve()
    44 {
    45     sort(a+1,a+N+1,cmp);
    46     for(int i=1;i <= N;++i)
    47         a[i].newVal=i;//离散化后的对应的值,虽然可能大小变了,但其对应的相对次序是不变的
    48     sort(a+1,a+N+1,cmp1);//恢复原数组对应的顺序
    49     int res=0;
    50     for(int i=1;i <= N;++i)
    51     {
    52         //Sum(a[i].newVal) : i 之前,数值不大于a[i].newVal 的个数
    53         //i-1-Sum(a[i].newVal) : i 之前,数值大于a[i].newVal的个数
    54         //而答案就是 max(i-1-Sum(a[i].newVal)
    55         res=max(res,i-1-Sum(a[i].newVal));
    56         Add(a[i].newVal);
    57     }
    58     printf("%d
    ",res+1);//最终结果要加1,因为不管当前交换完后是否有序,都需要额外输出一个 moo 来判断是否有序
    59 }
    60 int main()
    61 {
    62     scanf("%d",&N);
    63     for(int i=1;i <= N;++i)
    64     {
    65         scanf("%d",&a[i].val);
    66         a[i].id=i;
    67     }
    68     Solve();
    69 }
    View Code

      

  • 相关阅读:
    订单生成案例详解
    分页案例详解
    简单的多条件查询案例
    删除选中案例详解
    转账汇款案例
    登录操作记住用户名实现
    根据自定义异常来回显错误信息
    会话技术cookie和session详解
    JDBC
    Netty入门教程——认识Netty
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/9833435.html
Copyright © 2011-2022 走看看