跳到主要内容
原文182 词数1 分钟

题解:P12688 [KOI 2022 Round 1] 避开

概述

给定长度 n 的整数序列,一次操作交换相邻两数,要让奇数与偶数最多相邻一次,求最少交换次数。最终序列只能是奇数段接偶数段或偶数段接奇数段两种形态。做法是选定一种奇偶性全部压到左端,第 k 个该奇偶性元素从当前下标移到目标位置所需的交换次数即两下标之差,累加求和,两种情况取最小值。时间复杂度 O(n)。

题意简述​

给定长度为 nn 的整数序列 aa,一次操作可交换相邻两数。求最少交换次数,使序列中 奇数 与 偶数 最多相邻一次。

解题思路​

奇偶最多相邻一次,最终序列只能是 奇数段 + 偶数段 或 偶数段 + 奇数段。

选定一种奇偶性 p∈{ 0,1 }p\in\set{0,1} 全部压到左端。

对于第 kk 个奇偶性为 pp 的元素,当前下标为 ii,目标下标为 kk,需要交换 i−ki-k 次。

最终答案为 p=0p=0 和 p=1p=1 两种情况的最小值。

参考代码​

383 Bcpp
#include <bits/stdc++.h>
using namespace std;

using ll=long long;
const int N=1000005;
int a[N];
ll calc(int n,int p)
{
ll res=0,k=0;
for(int i=1;i<=n;i++)
{
if((a[i]&1)==p)res+=i-(++k);
}
return res;
}
int main()
{
ios::sync_with_stdio(false);
cin.tie(nullptr);
int n;
cin>>n;
for(int i=1;i<=n;i++)
{
cin>>a[i];
}
cout<<min(calc(n,0),calc(n,1))<<'\n';
return 0;
}