【CSP-J 2021】插入排序

【CSP-J 2021】插入排序 解题报告

1 题目链接

洛谷P2910

2 题目大意

题目名称:插入排序
题目大意:

H H H老师给了一个长度为 n n n的数组 a a a,数组下标从 1 1 1开始,并且数组中的所有元素均为非负整数。小 Z Z Z需要支持在数组 a a a上的 Q Q Q次操作,操作共两种,参数分别如下:

1   x   v 1~x~v 1 x v:这是第一种操作,会将 a a a 的第 x x x 个元素,也就是 a x a_x ax 的值,修改为 v v v。保证 1 ≤ x ≤ n 1 \le x \le n 1xn 1 ≤ v ≤ 1 0 9 1 \le v \le 10^9 1v109注意这种操作会改变数组的元素,修改得到的数组会被保留,也会影响后续的操作

2   x 2~x 2 x:这是第二种操作,假设 H 老师按照冒泡排序 (为什么题目叫做插入排序) a a a 数组进行排序,你需要告诉 H 老师原来 a a a 的第 x x x 个元素,也就是 a x a_x ax,在排序后的新数组所处的位置。保证 1 ≤ x ≤ n 1 \le x \le n 1xn注意这种操作不会改变数组的元素,排序后的数组不会被保留,也不会影响后续的操作

H H H老师不喜欢过多的修改,所以他保证类型 1 1 1的操作次数不超过 5000 5000 5000

3 解法分析

注意题目大意里最后一行才是重点
首先,我们易证如果对于某一个已排序的数组,单点修改一个值,我们可以通过前后各冒泡一次来保持有序

那么:

  1. O ( n log ⁡ n ) O(n\log n) O(nlogn)预处理。
  2. O ( Q n ) O(Qn) O(Qn)在线。

总复杂度: O ( Q n ) O(Qn) O(Qn)
由题目大意最后一行我们显然知道,它能 A A A

4 AC Code

#include 
#define int long long
#define S second
#define F first
using namespace std;

int n, q;
int a[8007];
pair <int, int> p[8007], cnt[8007];

signed main() {
	scanf("%lld%lld", &n, &q);
	for (int i = 0; i < n; ++i) {
		scanf("%lld", &p[i].F);
		p[i].S = i;
		cnt[i] = p[i];
	}
	sort(cnt, cnt + n);
	for (int i = 0; i < n; ++i)
		a[cnt[i].S] = i;
	while (q--) {
		int op;
		scanf("%lld", &op);
		if(op == 2) {
			int x;
			scanf("%lld", &x);
			printf("%lld\n", a[--x] + 1);
		}//这里O(1)查询
		else {
			int x, nn;
			pair <int, int> ln;
			scanf("%lld%lld", &x, &nn);
			ln = p[--x];
			p[x].first = nn;
			a[x] = 0;
			for (int i = 0; i < n; ++i) {
				if (i == x)
					continue;
				if (p[i] < p[x])
					++a[x];
				if (p[i] < ln && p[i] > p[x])
					++a[i];
				if (p[i] > ln && p[i] < p[x])
					--a[i];
			}
		}//O(n)排序
	}
	return 0;
}//本蒟蒻奇妙的码风

5 废话

今天 15 m i n 15min 15min (水) 写了两篇题解(然鹅我在打这场模拟的时候悲惨210
21J T2还是比较靠思维的吧
21J T3就是一纯纯板子
T4 链表模拟
(模拟的时候还是比较紧张吧,期望分数应该在 320 320 320~ 350 350 350

你可能感兴趣的:(CCF,题解,算法,排序算法)