[AGC003C] BBuBBBlesort! 题解
首先把这个序列离散化,变成一个 \(1\) 到 \(n\) 的排列。
这个操作 2 看起来很奇怪,我们把它重新写一下,它等价于:
- 交换 \(a_i\) 和 \(a_{i+2}\)。
这一操作做任意多次都是免费的,所以就相当于一开始以及做完一次操作 1 之后,我们可以对 \(a_1,a_3,a_5,\cdots\),\(a_2,a_4,a_6,\cdots\) 这两个序列任意排序,也就是下表为奇数和下标为偶数。
不过仅靠这样没法排序这个序列。因为奇数位上的数永远在奇数位置上,如果有一个数在排序好的数列中应当在偶数位置上,它无法被放到正确的位置上。
这时候就需要操作 1,显然这时候有对应一个应该处在奇数位置上但目前在偶数位置上的数,我们通过任意排序使它们相邻,然后用操作 1 交换,这样这两个数的位置的奇偶性正确了,可以通过任意排序把他们放到正确的位置。
我们统计出位置和目标位置奇偶性不同的数的数量 \(cnt\),每次操作可以归位两个,所以答案就是 \(\frac{cnt}{2}\)。
一次操作达成的效果不可能比这样更优,这么多操作是充分且必要的。
代码给一下吧。
离散化后这个数的值就是它的目标位置。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
#include <string>
using namespace std;
typedef long long LL;
LL n,ans = 0;
LL a[200005],b[200005];
int main(){
ios::sync_with_stdio(false);
cin >> n;
for(LL i = 1;i <= n;i ++){
cin >> a[i];
b[i] = a[i];
}
sort(b + 1,b + 1 + n);
for(LL i = 1;i <= n;i ++) a[i] = lower_bound(b + 1,b + 1 + n,a[i]) - b; // 离散化
for(LL i = 1;i <= n;i ++) if((a[i] & 1) != (i & 1)) ans ++;
ans >>= 1;
cout << ans << endl;
return 0;
}