C. AquaMoon and Strange Sort
对于最终所有数字的状态依然是 r i g h t right right 这个条件我们可以知道,每个数字只能被操作偶数次,也就是在奇数下标的数字最终只能停在奇数下标,偶数下标的数字最终只能停在偶数下标。所以,最终状态是 r i g h t right right 和 l e f t left left 只和最初和最终的位置有关,一个数字中间怎么被交换的根本就不用在意,而且相邻交换又没有其他限制,也就是一个数字最终要停在任何一个位置都是可以通过交换实现的(只要不是一个位置放两个数字),再说的明白点,就是可以通过相邻交换形成全排列中的任意一种。
那么根据我们上述讨论出来的结论,我们现在来讨论如何判断这个序列是否符合条件。因为数字不唯一,我们现在考虑某一种数字最终是否能够满足条件,最终每一种数字都能满足条件即输出
Y
E
S
YES
YES 。
某一种数字满足条件即满足以下两个条件:
①位置正确,由于最终序列要递增,某一种数字只能放在某一个区间内。
②状态正确:即最终状态都为
r
i
g
h
t
right
right
那么对于这一种数字我们先考虑位置正确:很显然,我们用排序后再二分的方式,可以找到这一种数字的范围必须放在
[
i
d
x
1
,
i
d
x
2
]
[idx1,idx2]
[idx1,idx2] 之间。
然后我们再考虑状态正确:我们这里假设这一种数字中有
x
x
x 个下标为奇数,
y
y
y 个下标为偶数。那么我们要让这
x
+
y
x+y
x+y 个数字的状态都正确,也就是
x
x
x 个数字最终必须放在下标为奇数的地方,
y
y
y 个数字最终必须放在下标为偶数的地方。然而我们在这之前要保证位置正确,也就是这
x
+
y
x + y
x+y 个数字只能放在
[
i
d
x
1
,
i
d
x
2
]
[idx1, idx2]
[idx1,idx2] 这个下标区间内,那么只要这个区间内有
x
x
x 个奇数下标,
y
y
y 个偶数下标,就又保证了位置正确,最终状态也都为
r
i
g
h
t
right
right ,这种数字才能被正确摆放。(注意:不要考虑是否能够摆放成这种情况,上述已经讨论过,根据相邻交换,可以将序列摆放成其全排列中的任一一种)
c o d e code code
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 2;
int g[N][2];
int n;
int a[N];
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
freopen("out.txt", "w", stdout);
#endif
int T;
scanf("%d", &T);
while(T--) {
bool ok = true;
scanf("%d", &n);
for (int i = 1; i <= n; ++i) {
scanf("%d", &a[i]);
g[a[i]][i & 1]++;
}
sort(a + 1, a + 1 + n);
for (int i = 1; i <= n; ++i) {
int idx1 = lower_bound(a + 1, a + 1 + n, a[i]) - a;
int idx2 = upper_bound(a + 1, a + 1 + n, a[i]) - a - 1;
int len = idx2 - idx1 + 1, odd, even;
if (len & 1) {
if (idx1 & 1) {
odd = len / 2 + 1;
even = len / 2;
}
else {
even = len / 2 + 1;
odd = len / 2;
}
}
else {
odd = even = len / 2;
}
if (even != g[a[i]][0] || odd != g[a[i]][1]) {
ok = false;
break;
}
}
if (ok) {
printf("YES\n");
}
else {
printf("NO\n");
}
for (int i = 1; i <= n; ++i) g[a[i]][0] = g[a[i]][1] = 0;
}
}