• 归并排序找逆序数


    题意:
        bobo has a sequence a 1,a 2,…,a n. He is allowed to swap two adjacent numbers for no more than k times. 
    Find the minimum number of inversions after his swaps. 
    Note: The number of inversions is the number of pair (i,j) where 1≤i<j≤n and a i>a j.
     

    Input

    The input consists of several tests. For each tests: 
    The first line contains 2 integers n,k (1≤n≤10 5,0≤k≤10 9). The second line contains n integers a 1,a 2,…,a n (0≤a i≤10 9).
     

    Output

    For each tests: 
    A single integer denotes the minimum number of inversions.
     

    Sample Input

    3 1
    2 2 1
    3 0
    2 2 1
     

    Sample Output

    1
    2
     
     
    分析:归并排序+贪心
         这里有个k要注意,就是可以交换相邻数字的位置,使得逆序数最小,那么我们肯定是把最小的数字往前换,这样我们算逆序数就只要把原来的逆序数算出来再减去可以交换的次数就好了,当然如果算出来是负数我们就让它直接等于零吧!
     
    代码:
     1 #include<iostream>
     2 using namespace std;
     3 const int maxn =100000+5;
     4 const int Q = 50000 + 5;
     5 int arr[maxn];
     6 int lef[Q], rig[Q];
     7 long long  ans;
     8 int lef_size;
     9 int rig_size;
    10 void Merger(int arr[], int L, int M, int R)
    11 {                                                     //归并整个数组
    12     int i, j, k;
    13     lef_size = M - L;
    14     rig_size = R - M;
    15     for (i = L; i < M; i++)
    16     {
    17         lef[i - L] = arr[i];                          //放在左边的数组
    18     }
    19     for (i = M; i < R; i++)
    20     {
    21         rig[i - M] = arr[i];                            //放在右边的数组
    22     }
    23     i = 0; j = 0; k = L;
    24     while (i < lef_size&&j < rig_size)
    25     {
    26         if (lef[i] <= rig[j])                         //左边数组小于右边数组
    27         { 
    28             arr[k] = lef[i];                           //把左边数组的数放进整合数组中
    29             i++;                                      //左数组下标加加
    30             k++;                                      //整合数组下标加加
    31             ans += j;                                  //逆序数加加(相当于在找i与下一个i之间插进去的数字,只要有数字插队,就表示
    32                                                         //左边(也可以说前面)大于了右边的数字(后面),所以加J,可能有点不好理解,
    33                                                            //自行脑补吧!)
    34         }
    35         else
    36         {
    37             arr[k] = rig[j];
    38             j++;
    39             k++;
    40         }
    41     }
    42     while (i < lef_size)
    43     {                                             //没有放完的左边的数
    44 
    45         arr[k] = lef[i];
    46         i++;
    47         k++;
    48         ans += j;
    49 
    50 
    51     }
    52     while (j < rig_size)
    53     {
    54         arr[k] = rig[j];
    55         j++;
    56         k++;
    57 
    58     }
    59 }
    60 void Mergersort(int arr[], int L, int R)
    61 {
    62     if (L + 1<R)                           //归并排序
    63     {
    64         int M = (L + R) / 2;
    65         Mergersort(arr, L, M);           
    66         Mergersort(arr, M, R);
    67         Merger(arr, L, M, R);
    68     }
    69 }
    70 int main()
    71 {
    72     int n;
    73     long long k;
    74     while (cin >> n>>k)
    75     {
    76         ans = 0;
    77         for (int m = 0; m < n; m++)
    78             cin >> arr[m];
    79         Mergersort(arr, 0, n);
    80         if (ans - k > 0)
    81             cout << ans - k << endl;               
    82         else
    83             cout << "0" << endl;
    84     }
    85     return 0;
    86 }
     
     
     
  • 相关阅读:
    JavaMail入门第四篇 接收邮件
    JavaMail入门第三篇 发送邮件
    JavaMail入门第二篇 创建邮件
    JavaMail入门第一篇 邮件简介及API概述
    Java对象数组
    Mybatis Dao层注解及XML组合Dao的开发方式
    spring mvc常用注解总结
    组建自己的局域网(可以将PC机实现为服务器)
    局域网 FTP建立,搭建一个简易的局域网服务器
    公司局域网搭建
  • 原文地址:https://www.cnblogs.com/Lynn0814/p/4711816.html
Copyright © 2020-2023  润新知