import
java.util.*;
/**
* Created by Daxin on 2017/8/19.
* <p/>
* 奶牛排队饮水问题
* 输入:n牛的数目,然后n个整数表示牛的序号
* 输出:输出交换最少次数
* <p/>
* 例如一个测试用例:9<br>
* 2,2,1,3,3,3,2,3,1<br>
* 输出:4
*
*在线题目地址:http://www.hustoj.com/oj/problem.php?id=1056
*
*
*/
public
class
CattleSortWater {
public
static
void
main(String[] args) {
// int[] nums = {2, 2, 1, 3, 3, 3, 2, 3, 1};
Scanner cin =
new
Scanner(System.in);
int
n = cin.nextInt();
int
[] nums =
new
int
[n];
for
(
int
i =
0
; i < n; i++) {
nums[i] = cin.nextInt();
}
System.out.println(solve(nums));
// System.out.println(Arrays.toString(nums));
}
public
static
int
solve(
int
[] nums) {
int
result =
0
;
Map<Integer, Integer> wcount =
new
TreeMap<>();
Map<Integer, Integer> range =
new
TreeMap<>();
for
(
int
num : nums) {
Integer tmp = wcount.get(num);
wcount.put(num, tmp ==
null
?
1
: tmp +
1
);
}
Set<Integer> set = wcount.keySet();
int
pre =
0
;
for
(
int
i : set) {
int
tmp = wcount.get(i) + pre;
range.put(i, tmp);
pre = tmp;
}
for
(
int
num : set) {
int
times = wcount.get(num);
int
ran = range.get(num);
for
(
int
i = ran -
1
, t = times; t >
0
; t--, i--) {
if
(nums[i] != num) {
int
r = get(nums, range.get(nums[i]), wcount.get(nums[i]), num);
if
(r != -
1
) {
//在nums[i] 区间中寻找到了num
int
tmp = nums[r];
nums[r] = nums[i];
nums[i] = tmp;
result++;
}
else
{
// 在希望区间没有找到,进行余下遇见全扫描
int
rr = getRange(nums, ran, num,range.get(nums[i])-wcount.get(nums[i]),range.get(nums[i]));
if
(rr != -
1
) {
int
tmp = nums[rr];
nums[rr] = nums[i];
nums[i] = tmp;
result++;
}
}
}
}
}
return
result;
}
/**
*
* @param nums 数组
* @param range 结束的下标
* @param times 出现的次数,range-times就是起始下标
* @param expect 希望查找的希望值
* @return
*/
public
static
int
get(
int
[] nums,
int
range,
int
times,
int
expect) {
for
(
int
i = range -
1
, t = times; t >
0
; t--, i--) {
if
(nums[i] == expect) {
return
i;
}
}
return
-
1
;
}
/**
*
* @param nums 数组
* @param start 查找的起始位置,结束位置是数组的结束
* @param expect 期望寻找到的值
* @param exceptStart 排除区域的起始下标
* @param exceptEnd 排除区域的结束下标
* @return 返回下标
*/
public
static
int
getRange(
int
[] nums,
int
start,
int
expect,
int
exceptStart,
int
exceptEnd) {
for
(; start < nums.length; start++) {
if
(start>=exceptStart&&start<exceptEnd)
continue
;
if
(nums[start] == expect) {
return
start;
}
}
return
-
1
;
}
}