Ultra-QuickSort
Time Limit: 7000MS | Memory Limit: 65536K | |
Total Submissions: 54036 | Accepted: 19856 |
Description
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.
Ultra-QuickSort produces the output
Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence.
Input
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.
Output
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.
Sample Input
5 9 1 0 5 4 3 1 2 3 0
Sample Output
6 0
Source
(1)树状数组求解的思路:
开一个能大小为这些数的最大值的树状数组,并全部置0。
从头到尾读入这些数,每读入一个数就更新树状数组,查看它前面比它小的已出现过的有多少个数sum,然后用当前位置减去该sum,就可以得到当前数导致的逆序对数了。把所有的加起来就是总的逆序对数。
(2)离散化!!!
输入的数最大999,999,999,如果直接开那么大的数组会导致树状数组无法开下,所以应使用离散化技巧。v存放原数组的元素,i存放原始位置,即node[i].i= i。
把这些结构体按照v的大小排序。
disp数组存放离散化后的值,即disp[node[i].i] = i。
这样从头到尾读入disp数组中的元素,即可以保持原来的大小关系,又可以节省大部分空间。
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct Node {
int v, i;
bool operator<(const Node& n) const {
return v < n.v;
}
};
typedef long long LL;
const int MAXN = 5e5 + 10;
int n, bit[MAXN], disp[MAXN];
Node node[MAXN];
int Sum(int x) {
int sum = 0;
while (x) {
sum += bit[x];
x -= x & -x;
}
return sum;
}
void Add(int x, int v) {
while (x <= n) {
bit[x] += v;
x += x & -x;
}
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
while (scanf("%d", &n), n) {
for (int i = 1; i <= n; ++i) {
scanf("%d", &node[i].v);
node[i].i = i;
}
//此处为离散化
sort(&node[1], &node[n + 1]);
for (int i = 1; i <= n; ++i) {
disp[node[i].i] = i;
}
memset(bit, 0, sizeof(bit));
LL ans = 0;
for (int i = n; i >= 1; --i) {
//注意disp[i] == 1时,肯定没有比他小的数
//所以要跳过disp为1的情况,否则会超时,因为0&-0 == 0
if (disp[i] > 1) ans += Sum(disp[i] - 1);
Add(disp[i], 1);
}
printf("%lld\n", ans);
}
return 0;
}