package Week3;
import java.io.BufferedReader;
import java.io.FileInputStream;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Comparator;
import java.util.StringTokenizer;
/*描述
在此问题中,您必须分析特定的排序算法。该算法通过交换两个相邻的序列元素来处理 n 个不同的整数序列,直到序列按上升顺序排序。对于输入序列
9 1 0 5 4 移动成升序的0 1 4 5 9最少移动的次数
您的任务是确定超快速排序需要执行多少交换操作才能对给定的输入序列进行排序。
输入
输入包含几个测试案例。每个测试案例都以包含一个整数 n < 500,000 的线开头 - 输入序列的长度。以下每个 n 行都包含一个整数 0 ≤ a [i] ≤ 999,999,999,
i-th 输入序列元素。输入按长度 n = 0 的序列终止。此序列不得处理。
输出
对于每个输入序列,您的程序打印一行包含整数操作,这是排序给定输入序列所需的交换操作的最小数量。
示例输入
5
9
1
0
5
4
3
1
2
3
0
样本输出
6
0*/
public class POJ2299 {
static int N;
static int tree[];//叶子节点初始化值,1,排序之后(升序排序,值相等索引升序),按原数组下标顺序处理,每处理一个元素,然后处理元素tree值-1
static int arr[][];
static long ans;
public static void main(String[] args) throws Exception{
System.setIn(new FileInputStream("Solution.txt"));
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
while(br.ready()) {
StringTokenizer st = null;
st = new StringTokenizer(br.readLine());
N = Integer.parseInt(st.nextToken());
if(N == 0) {
break;
}
arr = new int[N+1][2];
for (int i = 1; i <= N; i++) {
st = new StringTokenizer(br.readLine());
int x = Integer.parseInt(st.nextToken());
arr[i][0]=i;
arr[i][1]=x;
}
Arrays.sort(arr, 1, N+1, new Comparator<int[]>() {
@Override
public int compare(int[] o1, int[] o2) {
return o1[1]==o2[1]?o1[0]-o2[0]:o1[1]-o2[1];
}
});
int L =1;
while(L<N) {
L=L+L;
}
tree=new int[2*L];
ans =0;
for (int i = L; i <= 2*L-1; i++) {
update(i,1);//初始值默认1,当前已经处理数的有效个数都是1,每处理一个数,当前位置数更新成0;查询当前位置不包括当前位置,以左的数字之后是几,要移动的位置就是几
}
for (int i = 1; i <= N; i++) {
int idx = arr[i][0];
long q = query(L,L+idx-1-1);//下标从1开始,L+idx-1对应叶节点位置,查询前一个位置L+idx-1-1
ans+=q;
update(L+idx-1,tree[L+idx-1]-1);//每处理一个元素,该元素位置的叶子节点更新-1
}
System.out.println(ans);
}
}
private static long query(int s, int e) {
long result = 0;
while(s<=e) {
if(s%2==1) {
result=result+tree[s];
}
if(e%2==0) {
result=result+tree[e];
}
s=(s+1)/2;
e=(e-1)/2;
}
return result;
}
private static void update(int idx, int val) {
tree[idx]=val;
idx=idx/2;
while(idx>0) {
tree[idx]=tree[idx*2]+tree[idx*2+1];
idx=idx/2;
}
}
}