codeforces.848.B禁止的排列

@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;
}

以个人刷题整理为目的,如若侵权,请联系删除~

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值