又是一道套路题
算法:逆序对(归并排序)
(Large exttt{Solution})
题目应该很好理解,就不做赘述。
对于一个 (2*2) 的表格:
1 2
3 4
旋转一次后:
4 3
2 1
可以发现每一列的两个数字是永远呆在一起的,只是上下可能会调换位置。
所以我们可以判断是否有解的问题:以第一个表格第一行作为关键字建桶,将第二行的数放入桶中,与之对应,再遍历第二个表格。
若在 (b[i][j]) 找到一个关键字 (令这个数字在第一个表格中为 (a[n][m]) )判断:
-
与 (b[i][j]) 同一列的数是否等于 与(a[n][m]) 同一列的数。
-
若 (|m-j|)为奇数,则这一列数字肯定反转了奇数次,则这一列数字一定顺序相反。
-
若 (|m-j|)为偶数,则这一列数字肯定反转了偶数次,则这一列数字一定顺序一样。
然后就是求解。
因为同一列的数永远不会分离,所以将它们看作同一个数,每次旋转,意义就是交换 (i) 和 (i+1) 两个数,然后你就会发现这就是一道经典的逆序对问题。
最后,不要忘记特判列数等于 (1) 的情况。
(Large exttt{Code})
#include <bits/stdc++.h>
using namespace std;
const int N = 1e7;
#define int long long
#define MP make_pair
int a, s1[2][N + 10], s2[2][N + 10], top, s[N + 10], l[N + 10], ans, st[N + 10];
void msort(int n, int m)
{
if (n == m)
return;
int mid = (n + m) / 2;
msort(n, mid);
msort(mid + 1, m);
int i = n, j = mid + 1, k = n;
while (i <= mid && j <= m)
{
if (s[i] > s[j])
{
l[k++] = s[j++];
ans += mid - i + 1;
}
else
{
l[k++] = s[i++];
}
}
while (i <= mid)
l[k++] = s[i++];
while (j <= m)
l[k++] = s[j++];
for (int i = n; i <= m; i++)
s[i] = l[i];
}
signed main()
{
scanf("%lld", &a);
for (int i = 0; i <= 1; i++)
for (int j = 1; j <= a; j++)
scanf("%lld", &s1[i][j]);
for (int i = 0; i <= 1; i++)
for (int j = 1; j <= a; j++)
scanf("%lld", &s2[i][j]);
for (int i = 1; i <= a; i++) st[s1[0][i]] = i;//以第一行为关键字将第二行数字放入桶中
if (a == 1)//考场上写的11分代码
{
if (s1[0][1] == s2[0][1] || s1[1][1] == s2[1][1])
puts("0");
else
puts("dldsgay!!1");
return 0;
}
else if (a == 2)
{
if (s1[0][1] == s2[0][1] && s1[1][1] == s2[1][1] && s1[0][2] == s2[0][2] && s1[1][2] == s2[1][2])
puts("0");
else if (s1[0][1] == s2[1][2] && s1[1][2] == s2[0][1] && s1[0][2] == s2[1][1] && s1[1][1] == s2[0][2])
puts("1");
else
puts("dldsgay!!1");
return 0;
}
for (int i = 1; i <= a; i++)//判断是否有解以及建造一个要排序的数组s
{
if (st[s2[0][i]])
{
if ((i - st[s2[0][i]]) & 1)
{
puts("dldsgay!!1");
return 0;
}
s[i] = st[s2[0][i]];
continue;
}
else if (st[s2[1][i]])
{
if ((i - st[s2[1][i]]) & 1 == 0)
{
puts("dldsgay!!1");
return 0;
}
s[i] = st[s2[1][i]];
continue;
}
puts("dldsgay!!1");
return 0;
}
for (int i = 1; i <= a; i++)
if (!s[i])
{
puts("dldsgay!!1");
return 0;
}
msort(1, a);
printf("%lld", ans);
return 0;
}