@toc
问题描述
给定一个长度为 n 的排列 p、一个由 m 个不同的整数 a1,a2,…,am (1≤ai≤n) 组成的数组和一个整数 d。
设 pos(x) 是排列 p 中 x 的索引。数组 a 不好,如果
pos(ai)<pos(ai+1)≤pos(ai)+d 表示所有 1≤i<m.
例如,排列 p=[4,2,1,3,6,5] 和 d=2:
a=[2,3,6] 是一个不好的数组。
a=[2,6,5] 很好,因为 pos(a1)=2, pos(a2)=5,所以条件 pos(a2)≤pos(a1)+d 不满足。
a=[1,6,3] 很好,因为 pos(a2)=5, pos(a3)=4,所以条件 pos(a2)<pos(a3) 不满足。
在一次移动中,您可以交换排列 p 的两个相邻元素。使数组 a 变得良好的最小移动次数是多少?可以证明,始终存在一系列移动,因此数组 a 变得良好。
排列是由 n 个从 1 到 n 的不同整数组成的数组,顺序任意。例如,[2,3,1,5,4] 是排列,但 [1,2,2] 不是排列(2 在数组中出现两次),[1,3,4] 也不是排列(n=3,但数组中有 4)。
格式输入
输入
每个测试包含多个测试用例。第一行包含测试用例 t (1≤t≤104) 的数量。测试用例的说明如下。
每个测试用例的第一行包含三个整数 n、m 和 d (2≤n≤105、2≤m≤n、1≤d≤n)、排列 p 的长度、数组 a 的长度和 d 的值。
第二行包含 n 个整数 p1,p2,…,pn (1≤pi≤n, pi≠pj 表示 i≠j)。
第三行包含 m 个不同的整数 a1,a2,…,am (1≤ai≤n, ai≠aj 表示 i≠j)。
所有测试用例的 n 总和不超过 5⋅105。
格式输出
输出
对于每个测试用例,打印所需的最小移动次数,以使数组 a 变得良好。
样例输入
5
4 2 2
1 2 3 4
1 3
5 2 4
5 4 3 2 1
5 2
5 3 3
3 4 1 5 2
3 1 2
2 2 1
1 2
2 1
6 2 4
1 2 3 4 5 6
2 5
样例输出
1
3
2
0
2
评测用例规模与约定
每次测试的时间限制2 秒
每个测试的内存限制256 MB
解析
注意
在第一种情况下,pos(a1)=1,pos(a2)=3.为了使阵列好,一种方法是交换p3和p4.之后,数组一个会很好,因为条件pos(a2)≤pos(a1)+d不会满意的。
在第二种情况下,pos(a1)=1,pos(a2)=4.这3移动可能是:
交换p3和p4.
交换p2和p3.
交换p1和p2.
在这些移动之后,排列p将是[2,5,4,3,1].数组一个会很好,因为条件pos(a1)<pos(a2)不会满意的。可以证明你不能制作数组一个 好,动作少。
在第三种情况下,pos(a1)=1,pos(a2)=3,pos(a3)=5.这2移动可以是:
交换p4和p5.
交换p3和p4.
在这些移动之后,排列p将是[3,4,2,1,5].数组一个会很好,因为条件pos(a2)<pos(a3)不会满意的。可以证明你不能制作数组一个 好,动作少。
在第四种情况下,pos(a1)=2,pos(a2)=1.数组一个已经不错了。
在第五个案例中,pos(a1)=2,pos(a2)=5.这2动作是:
交换p1和p2.
交换p5和p6.
参考程序
#include <iostream>
#include<algorithm>
#include<vector>
using namespace std;
using i64 = long long;
void solve() {
int n, m, d;
cin >> n >> m >> d;
vector<int> pos(n);
for (int i = 0; i < n; i++) {
int p;
cin >> p;
p--;
pos[p] = i;
}
vector<int> a(m);
for (int i = 0; i < m; i++) {
cin >> a[i];
a[i]--;
}
int ans = n;
for (int i = 1; i < m; i++) {
int x = pos[a[i - 1]], y = pos[a[i]];
if (d >= n - 1) {
ans = min(ans, max(0, y - x));
}
else {
ans = min(ans, max(0, min(d + 1 - (y - x), y - x)));
}
}
cout << ans << "\n";
}
int main() {
ios::sync_with_stdio(false);
cin.tie(nullptr);
int t;
cin >> t;
while (t--) {
solve();
}
return 0;
}
以个人刷题整理为目的,如若侵权,请联系删除~