# 优秀数组
# 解题思路
1、初始分析
- 给定一个排列
p,我们首先构建一个pos数组,使得pos[i]表示i在排列p中的位置。 - 我们需要判断数组
a是否是一个优秀数组,即pos[a[i]] < pos[a[i+1]] <= pos[a[i]] + d对于所有i都成立。 - 我们的目标是通过最少的相邻元素交换,使得数组
a不再是一个优秀数组。
2、思路
- 要使数组
a不再是优秀数组,我们只需要打破条件pos[a[i]] < pos[a[i+1]] <= pos[a[i]] + d中的某一个。 - 一种简单的做法是让
pos[a[i]]和pos[a[i+1]]之间的距离超过d,或者直接让pos[a[i]] >= pos[a[i+1]]。
3、具体方法
- 只需要考虑
a中相邻元素的顺序,并判断如何交换p中相邻元素使得其顺序被打破。 - 假设我们需要在
p中交换某些元素来实现上述目标,那么最小的交换次数是将a[i]和a[i+1]的位置交换。 - 如果
pos[a[i]] + 1 == pos[a[i+1]],则需要一步交换。
4、特别情况
- 还需要考虑,如果通过交换相邻元素无法解决问题的情况。比如
pos[a[i+1]]的位置无法移到pos[a[i]]的前面或超过d。
C++代码如下:
#include <iostream>
#include <vector>
#include <algorithm>
#include <climits>
using namespace std;
int main() {
int n, m, d;
cin >> n >> m >> d;
vector<int> p(n + 1);
vector<int> pos(n + 1);
// 读取排列 p,并构建位置数组 pos
for (int i = 1; i <= n; i++) {
cin >> p[i];
pos[p[i]] = i;
}
vector<int> a(m);
for (int i = 0; i < m; i++) {
cin >> a[i];
}
int min_operations = INT_MAX;
// 遍历数组 a 的相邻元素
for (int i = 0; i < m - 1; i++) {
int current_pos = pos[a[i]];
int next_pos = pos[a[i + 1]];
// 检查 pos[a[i]] < pos[a[i+1]] <= pos[a[i]] + d 是否成立
if (current_pos < next_pos && next_pos <= current_pos + d) {
// 计算需要的最少操作次数
int distance = next_pos - current_pos;
// Case 1: 交换 current_pos 和 next_pos
min_operations = min(min_operations, distance);
// Case 2: 如果 next_pos + d <= n,考虑使 pos[a[i+1]] 超过 pos[a[i]] + d
if (current_pos + d + 1 <= n) {
min_operations = min(min_operations, d + 1 - distance);
}
} else {
min_operations = 0;
}
}
cout << min_operations << endl;
return 0;
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
时间复杂度为 O(m)
@2021-2025 代码随想录 版权所有 粤ICP备19156078号