/*
ID:lvfuan11
PROG:sort3
LANG:C++
translation:
有1,2,3三个数字组成的数列,现在要将其变成有序数列,求最少要交换多少次。
solution:
首先定义两个数字如果交换后都在正确的位置上,那么称这两个数字为交叉相等。所以根据贪心的思路很容易想到交叉相等的
数字肯定要交换。这样将所有交叉相等的数字处理完后就完成了算法的第一步。
那么如何处理剩下的数字?这里有个规律,就是剩下的数字肯定是3的倍数(证明见note),且两两不交叉相等。意味着只要
以3个数字为1组,一一处理即可。一组三个数字需要交换2次。统计出来这次的交换次数,加上第一步的交换次数就是答案。
note:
* 为什么说剩下的数字个数肯定是3的倍数?
首先定义p(i,j)=k的意义为,某位置上原本出现数字i,现在却出现数字j的位置有k个。则有一个推论:p(2,1)>0和
p(2,3)>0不会同时存在(p(1,2)和p(1,3), p(3,1)和p(3,2)同理)。因为假如两个都同时大于0,则1的位置上只能有
3,因为经过第一步后p(1,2)和p(2,1)相互抵消,p(2,1)>0则p(1,2)肯定已经为0!同理3的位置上也只能出现1。那么就有
p(3,1)>0 且 p(1,3)>0同时存在,那么就可以继续执行第一步,相互矛盾。故推论成立!
证明推论之后就简单了,假设有:
p(2,1)=x0;
p(2,3)=x1;
p(1,2)=x2;
p(1,3)=x3;
p(3,2)=x4;
p(3,1)=x5;
则根据上述推论,若x0不为0,那么x1=x2=0,若x4不等0,则x5肯定为0.那么剩下的数字个数为x0+x3+x4,可以发现这三个数肯定相等
,因为若不等的话,那么结果无论怎么交换都无法交换到正确的顺序上。得证
*/
#include <iostream>
#include <cstdio>
#include <set>
#include <algorithm>
using namespace std;
const int maxn = 1000 + 5;
int a[maxn], b[maxn], n;
set<int> rightPos[4];
inline bool inPos(int x, int p)
{
if(rightPos[x].find(p) != rightPos[x].end()) return true;
else return false;
}
int main()
{
freopen("sort3.in", "r", stdin);
freopen("sort3.out", "w", stdout);
while(~scanf("%d", &n)) {
for(int i = 1; i <= 4; i++) rightPos[i].clear();
for(int i = 1; i <= n; i++) {
scanf("%d", &a[i]);
b[i] = a[i];
}
sort(b + 1, b + n + 1);
for(int i = 1; i <= n; i++) {
rightPos[b[i]].insert(i);
}
int ans = 0;
for(int i = 1; i <= n; i++) {
if(inPos(a[i], i)) continue;
for(int j = 1; j <= n; j++) if(i != j) {
if(inPos(a[i], j) && inPos(a[j], i)) {
swap(a[i], a[j]);
ans++;
break;
}
}
}
int res = 0;
for(int i = 1; i <= n; i++)
if(a[i] != b[i]) res++;
printf("%d\n", ans + res / 3 * 2);
}
return 0;
}