CF1365F 再次交换
1 CF1365F 再次交换
2 题目描述
时间限制 \(2s\) | 空间限制 \(256M\)
\(Ayush, Ashish\) 和 \(Vivek\) 在准备下一轮 \(Codeforces\) 的新题,想检查下他们的测试样例是不是有效。
每个测试样例包括一个整数 \(n\) 和两个大小为 \(n\) 的数组 \(a\) 和 \(b\)。如果按照下面的操作一些次数(可以为零次)后数组 \(a\) 可以转换为数组 \(b\),输入数据任务是有效的,否则是无效的。数组 \(a\) 的操作如下:
- 选择一个整数 \(k (1≤𝑘≤⌊\frac{n}{2}⌋)\)。
- 交换长度为 \(k\) 的前缀。
例如,如果数组 \(a\) 的初始数据为 \({1,2,3,4,5,6}\),在执行完 \(k=2\) 的操作后,转换为 \({5,6,3,4,1,2}\)。给出一组测试数据,检查每一个是有效的还是无效的。
数据范围:测试样例的组数 \(t: (1≤𝑡≤500)\), 数组的大小 \(n: (1≤𝑛≤500)\), 数组 \(a_i, b_i\) 的个数:\(1≤𝑎_𝑖,b_i≤10^9)\)。
3 题解
结论:所有在 \(a\) 数组中对称的数一定在 \(b\) 数组中对称。
证明:对于长度为 \(k\) 的一次交换,位于 \(i\) (不妨设 \(i \le \lfloor \dfrac{n}{2} \rfloor\))的数会变成 \(n - k + i\)。位于 \(n-i+1\) 的数会变成 \(k - (n - (n - i + 1))\),也就是 \(k - i +1\)。而由于 \(n - (n - k + i) + 1\) 也等于 \(k - i + 1\),所以在交换一次后两数仍然对称。由此看来,交换无数次后两数也仍然对称。
我们可以枚举 \(a\) 数组中所有的对称数对,然后在 \(b\) 数组中查找改数对是否出现过。注意我们在 \(b\) 数组找到后要用 \(f\) 数组标记某个位置是否走过。如果我们再次枚举到了枚举到过的位置就需要跳出,否则答案可能错误。需要注意的是吗,对于 \(n\) 为奇数的情况,我们最好特判 \(a\)、\(b\) 数组中第\((n+1)/2\) 位是否相同,如果不是则直接跳出。这是因为在题目规定中我们不能改变第 \(\lceil \dfrac{n}{2} \rceil\) 位的值。
4 代码(空格警告):
#include <iostream>
#include <cstring>
using namespace std;
const int N = 505;
int T, n, y, yy;
int a[N], b[N];
int flag, flag2;
bool f[N];
int main()
{
cin >> T;
while (T--)
{
flag2 = 0;
memset(f, 0, sizeof(f));
cin >> n;
for (int i = 1; i <= n; i++) cin >> a[i];
for (int i = 1; i <= n; i++) cin >> b[i];
if (n % 2 && a[(n+1)/2] != b[(n+1)/2])
{
cout << "nO" << endl;
continue;
}
for (int i = 1; i <= n/2; i++)
{
y = n-i+1;
flag = 0;
for (int j = 1; j <= n/2; j++)
{
if (f[j]) continue;
yy = n-j+1;
if ((a[i] == b[j] && a[y] == b[yy]) || (a[i] == b[yy] && a[y] == b[j]))
{
f[j] = 1;
flag = 1;
break;
}
}
if (!flag)
{
cout << "nO" << endl;
flag2 = 1;
break;
}
}
if (!flag2)
{
cout << "yEs" << endl;
continue;
}
}
return 0;
}