zoukankan      html  css  js  c++  java
  • CodeForces 362C

    分析:首先我们要知道调用swap()函数的次数跟什么有关。可以观察发现在Insertion Sort里,当且仅当a[j](j∈[0,i)) > a[i]时会调用一次swap(),也就是说有多少个a[j](j∈[0,i)) > a[i]成立就会调用多少次swap()(因为a[i]前面的序列都是有序的),这个数目也叫逆序数。所以要使调用swap()的次数最少,就应该要使整个序列的总的逆序数最小。这时,我们可以枚举所有不同的两个位置对换之后的总逆序数来找最小的总逆序数。但枚举的时候我们需要知道a[i]与a[j]对换之后各自的逆序数以及对换之前的逆序数,记为b[i][j]、b[j][i]、b[i][i]、b[j][j]。因为我们对换a[i]和a[j]的行为只会影响到i~j上的元素的逆序数,我们可以用b[i][j]、b[j][i]、b[i][i]、b[j][j]推导出对换之后的总逆序数的增量。只要求出这个最小的增量我们就可以求得最小的总逆序数。

    那现在的关键就是比较快的求出数组b的所有元素的值。这个可以在O(n^2)的时间内完成。在n <= 5000的条件下应该还是可以接受的。

    这道题花了不少时间,主要原因在于没把推导的公式写得清清楚楚,虽然知道推导公式的方法,但是没有很快的推出正确的公式。

     1 #include <iostream>
     2 #include <queue>
     3 #include <string>
     4 #include <cstring>
     5 #include <algorithm>
     6 #include <cstdio>
     7 #include <map>
     8 #include <vector>
     9 using namespace std;
    10 int a[5000], b[5000][5000], n;
    11 int main(){
    12     cin >> n;
    13     for (int i = 0; i < n; i++){
    14         cin >> a[i];
    15     }
    16     for (int i = 0; i < n; i++){
    17         for (int j = 0; j < n; j++){
    18             b[i][j] = -1;
    19         }
    20     }
    21     for (int i = 0; i < n; i++){
    22         b[i][0] = 0;
    23         for (int j = 0; j < i; j++){
    24             if (a[i] < a[j]){
    25                 b[i][j + 1] = b[i][j] + 1;
    26             }else{
    27                 b[i][j + 1] = b[i][j];
    28             }
    29         }
    30         for(int j = i + 1;j < n;j++){
    31             if(a[i] < a[j]){
    32                 b[i][j] = b[i][j - 1] + 1;
    33             }else{
    34                 b[i][j] = b[i][j - 1];
    35             }
    36         }
    37     }
    38     int ans = 0;
    39     map<int,int> m;
    40     for (int i = 0; i < n; i++){
    41         for (int j = i + 1; j < n; j++){
    42             int x = 2 * (b[i][j] - b[i][i] + b[j][i] - b[j][j]) - (a[i] < a[j]?1:0) + (a[i] > a[j]?1:0);
    43             m[x]++;
    44             ans = min(ans,x);
    45         }
    46     }
    47     int counter = 0;
    48     for (int i = 1; i < n; i++){
    49         int j = i;
    50         while (j > 0 && a[j] < a[j - 1])
    51         {
    52             swap(a[j], a[j - 1]); // swap elements a[j] and a[j - 1]
    53             counter++;
    54             j = j - 1;
    55         }
    56     }
    57     cout << counter + ans << " " << m[ans] << endl;
    58     return 0;
    59 }
  • 相关阅读:
    图片上传记得要讲中文的重命名
    hihoCoder #1471 拥堵的城市
    搜狗拼音输入法的快捷键和其他应用快捷键冲突
    Codeforces #765D
    训练记录
    hihoCoder 1367 等式填空
    hihoCoder #1073 光棍节
    计算几何 I. 极角
    hihoCoder #1065 全图传送
    树的点分治专题
  • 原文地址:https://www.cnblogs.com/ZShogg/p/3426071.html
Copyright © 2011-2022 走看看