#P15810. [JOI 2013 Final] バブルソート

[JOI 2013 Final] バブルソート

说明

冒泡排序 是一种对序列进行排序的算法。假设我们想将一个长度为 NN 的数列 AA 按升序排序。冒泡排序会检查相邻的两个数,如果它们的大小关系不正确,就交换它们的位置。这一过程是通过从前向后扫描数列来完成的。也就是说,如果存在 Ai>Ai+1A_i > A_{i+1} 的位置,就交换这两个数,并且按照 i=1,2,,N1i = 1, 2, \dots, N-1 的顺序对每个 ii 执行一次检查,这称为一次扫描。已知,重复进行 N1N-1 次这样的扫描,就可以将数列按升序排序。

数列 AA冒泡排序交换次数,是指将上述算法应用于数列 AA 时,发生整数交换的次数。(已知的冒泡排序算法及其实现可能在循环顺序、范围以及终止条件等方面存在细微差异。但已知的是,当应用于同一数列时,整数交换次数不会因这些差异而改变。)

例如,以下程序是用 C 语言编写的、使用冒泡排序对长度为 nn 的整数数组 aa 进行排序的函数。

void bubble_sort(int *a, int n) {
    int i, j;
    for (i = 0; i < n - 1; ++i) {
        for (j = 0; j < n - 1; ++j) {
            if (a[j] > a[j + 1]) {
                /* 以下 3 行对应一次整数交换 */
                int x = a[j];
                a[j] = a[j + 1];
                a[j + 1] = x;
            }
        }
    }
}

任务

给定一个长度为 NN 的数列 AA。假设通过交换数列 AA 中任意位置的两个整数一次(仅一次),得到一个新的数列 AA'。编写一个程序,求出数列 AA' 的冒泡排序交换次数的最小值。(请注意,最初交换的两个整数不一定是相邻的。)

输入格式

从标准输入读取以下数据。

  • 第一行包含一个整数 NNNN 表示数列 AA 的长度。
  • 接下来的 NN 行中,第 ii 行 (1iN1 \leq i \leq N) 包含一个整数 AiA_i。这表示数列 AA 的第 ii 个整数。

输出格式

向标准输出输出一行,包含一个整数,表示数列 AA' 的冒泡排序交换次数的最小值。

5
10
3
6
8
1
0
5
3
1
7
9
5
2
3
1
2
3
1

提示

样例解释 1

如果交换数列 AA 开头的 1010 和结尾的 11,那么数列 AA' 将成为已排序的序列,其冒泡排序交换次数为 00

样例解释 2

如果交换数列 AA 中第三个的 77 和最后一个的 55,那么数列 AA' 变为 3,1,5,9,73, 1, 5, 9, 7AA' 的冒泡排序交换次数为 22

样例解释 3

即使数列 AA 最初就是已排序的,在构造数列 AA' 时也必须进行一次交换。

限制

1N1000001 \leq N \leq 100\,000 数列 AA 的长度
1Ai10000000001 \leq A_i \leq 1\,000\,000\,000 数列 AA 中数字的大小

评分标准

在评分数据中,占分值 10% 的部分满足 N1000N \leq 1000,且对于任意 i,ji, j (1i<jN1 \leq i < j \leq N) 有 AiAjA_i \neq A_j
在评分数据中,占分值 30% 的部分满足 N5000N \leq 5000,且对于任意 i,ji, j (1i<jN1 \leq i < j \leq N) 有 AiAjA_i \neq A_j
在评分数据中,占分值 80% 的部分满足对于任意 i,ji, j (1i<jN1 \leq i < j \leq N) 有 AiAjA_i \neq A_j


翻译由 DeepSeek V3.2 完成