题解:
最后要求得出的序列只有两种情况
- 奇数 偶数 奇数 偶数…
- 偶数 奇数 偶数 奇数…
首先统计奇数和偶数的个数
如果奇数与偶数个数差大于1的话,那么肯定没有答案的,输出-1
如果奇数的个数大于偶数的个数,那么第一个数肯定是奇数,看所有奇数是否在它应该在的位置上
如果偶数的个数大于奇数的个数,那么第一个数肯定是偶数,看所有偶数是否在它应该在的位置上
如果奇数个数与偶数个数相同的话,就需要找两种情况的最小值
代码如下:
int main ()
{
int T;
cin >> T;
while (T -- )
{
int n;
scanf("%d", &n);
vector<int> odd, even;
//odd存所有奇数的位置,even存所有偶数的位置
for (int i = 0; i < n; i ++ )
{
int x; scanf("%d", &x);
if (x & 1) odd.push_back(i);
else even.push_back(i);
}
// 奇数的个数,偶数的个数
int cnt_o = odd.size(), cnt_e = even.size();
if (n == 1) printf("0\n");
else if (abs(cnt_e - cnt_o) > 1) printf("-1\n");
else
{
LL ans = 0, pos = 0, tmp = 0;
//如果相应的数不在相应的位置,那么移动的操作数就是abs(i - pos)
//模拟一下即可,不难发现
if (cnt_e < cnt_o)
{
for (auto i : odd)
{
ans += abs(i - pos);
pos += 2;
}
printf("%lld\n", ans);
}
else if (cnt_e > cnt_o)
{
for (auto i : even)
{
ans += abs(i - pos);
pos += 2;
}
printf("%lld\n", ans);
}
else
{
for (auto i : odd)
{
ans += abs(i - pos);
pos += 2;
}
pos = 0;
for (auto i : even)
{
tmp += abs(i - pos);
pos += 2;
}
printf("%lld\n", min(ans, tmp));
}
}
}
return 0;
}