传送门 POJ2299
描述
In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input sequence
9 1 0 5 4 ,
Ultra-QuickSort produces the output
0 1 4 5 9 .
Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence.
输入
The input contains several test cases. Every test case begins with a line that contains a single integer n < 500,000 — the length of the input sequence. Each of the the following n lines contains a single integer 0 ≤ a[i] ≤ 999,999,999, the i-th input sequence element. Input is terminated by a sequence of length n = 0. This sequence must not be processed.
输出
For every input sequence, your program prints a single line containing an integer number op, the minimum number of swap operations necessary to sort the given input sequence.
样例
- Input
5
9
1
0
5
4
3
1
2
3
0- Output
6
0
题解
- 题意:给你一个整型数组,用相邻两个元素两两交换的方式使得整个数列从小到大排列,求出需要交换的次数
- 题意简单来说就是用冒泡排序需要交换多少次,但是我们都知道冒泡排序的时间复杂度是,暴力模拟肯定是会超时的。通过观察我们不难发现,交换次数的总和其实就是数列的逆序数之和(所谓逆序数就是在该元素之前比他大的元素个数),所以我们求出每一个元素的逆序数然后加起来就可以求出总共的交换次数。
- 我们首先通过快排求出所有元素应在的位置,用数组t来存放他们的出现状态,然后遍历原来的数组,每一次将每一个元素填入它应在的位置i(t[i]++),然后算出它前面出现过的n个数(包括自身),这n个数都是比它小的,我们用它当前位置减去n就可以知道在原序列中在他前面有多少个数比他大,也就是他的逆序数。
- 上面的单点修改区间求和这样的方法计算的话时间复杂度依旧是,所以我们使用树状数组进行优化,这样时间复杂度就变成了
1 |
|
PS
当数组元素都属于0~n时,可以直接使用以下方式:
1
2
3
4
5 for(int i=1;i<=n;i++){
scanf("%d",&a[i]);
add(a[i]+1,1); //+1是防止0造成死循环
ans+=i-sum(a[i]+1);
}