传统题 2000ms 512MiB

插入排序

该比赛已结束,您无法在比赛模式下递交该题目。您可以点击“在题库中打开”以普通模式查看和递交本题。

Problem Description

​ 小王在上算法设计与分析的课程中首次接触到插入排序,插入排序的基本原理如下:

​ 给定数组aa,假如a[1:i]a[1 : i]有序,考虑将 ai+1a_{i + 1} 插入到有序子数组a[1:i]a[1 : i]中. 用一个辅助变量记录 ai+1a_{i + 1},即 key=ai+1key = a_{i + 1}. 接下来,我们从索引 ii 逆向遍历到 11,如果发现 aj>keya_{j} > key,则将 aja_{j} 移动到 aj+1a_{j + 1},直到找到索引pp ,使得 ap≤keya_{p} \le key, 将 keykey 插入到 ap+1a_{p + 1} 中, 即 ap+1=keya_{p + 1} = key.显然,a[1:i+1]a[1 : i + 1] 保持有序。迭代上述过程,直到插入最后一个元素 ana_{n}, 以使得数组aa 有序.

​ 此外,插入排序的C语言代码如下:

//	数组下标从1开始.
void insertionSort(int a[], int n) {
    //	默认 a[1 : 1] 有序
    for (int i = 2; i <= n; i++) {
        int key = a[i];
        int j = i - 1;
        while (j >= 1 && a[j] > key) {
            a[j + 1] = a[j];
            j--;
        }
        a[j + 1] = key;
    }
}

​ 小王微调上述代码并定义一个calc(a,n)calc(a, n) 函数以估算插入排序的计算量,其代码如下:

//	数组下标从1开始.
int calc(int a[], int n) {
    int total = 0;
    //	默认 a[1 : 1] 有序
    for (int i = 2; i <= n; i++) {
        int key = a[i];
        int j = i - 1;
        while (j >= 1 && a[j] > key) {
            a[j + 1] = a[j];
            j--;
            total += 1;
        }
        a[j + 1] = key;
    }
    return total;
}

​ 基于上述灵感,小王决定出一道校赛题,题目描述如下:

​ 给定一个 nn 长的整数数组 aa,要求计算 calc(a,n)calc(a, n). 小王认为该问题太简单了(直接套用上述代码即可, hah),因此决定加大题目难度。

​ 增加 qq 次修改操作,每次操作在数组的末尾插入新元素 xx。注意,修改操作是持久的。 每次修改数组后,计算一次 calc(a′,n′)calc(a', n'). (a′a' 表示修改后的数组, n′n'表示修改后的数组长度)

Input Format

​ 第一行输入一个整数 nn (1≤n≤1051 \le n \le 10^{5}) 和一个正整数 qq (1≤q≤1051 \le q \le 10 ^ {5}),表示原数组aa 的初始长度和修改操作次数。

​ 第二行输入 nn 个正整数,表示初始数组的第ii个元素aia_{i}.

​ 接下来的第 33 到 q+2q + 2 行,每行输入一个正整数 xx ,表示新加入数组 aa 的末尾的元素 xx.

Output Format

​ 输出 q+1q + 1行非负整数,其中第一行表示初始数组对应的 calc(a,n)calc(a, n), 第 i+1i + 1 行表示第 ii 次修改后对应的calc(a′,n′)calc(a', n').

Sample

输入 #1

3 2
2 3 3
1
3

输出 #1

0
3
3

输入 #2

3 1
3 1 3
3

输出 #2

1
1

Hint

确保 1≤ai≤1091 \le a_{i} \le 10^9, 允许数组的元素重复.

重庆邮电大学第十九届ACM程序设计大赛(现场赛)

未参加
状态
已结束
规则
XCPC
题目
11
开始于
2025-3-22 13:10
结束于
2025-3-22 18:10
持续时间
5 小时
主持人
参赛人数
3