Description

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总体思路:
由于a[i]的范围太大,故不可能以a[i]的值为下标创建树状数组,需要进行离散化处理。离散化处理的结果要求和原有数据的次序保持一致,这样我们就可以用离散化处理后的结果来代替原有的数据进行相关计算。离散化处理的主要步骤如下:
struct Node
{
int val;
int pos;
};
Node node[MAXN];
int reflect[MAXN];
sort(node, node + MAXN, cmp)//按实际情况进行处理
reflect[node[i].pos] = i;
//val存放原数组的元素,pos存放原始位置,即node[i].pos = i。
//把这些结构体按照val的大小排序。
//reflect数组存放离散化后的值,即reflect[node[i].pos] = i。
//这样从头到尾读入reflect数组中的元素,即可以保持原来的大小关系,又可以节省大部分空间。
处理好后reflect数组的次序和原有数据的次序保持一致,因此可以代替原有的数据进行相关计算。
代码如下:
#include<iostream>
#include<vector>
#include<string>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 500010;
int a[MAXN];
int n;
int lowbit(int t)
{
return t&(-t);
}
void update(int t, int d)
{
while (t <= n)
{
a[t] += d;
t += lowbit(t);
}
}
long long getsum(int t)
{
long long sum(0);
while (t > 0)
{
sum += a[t];
t -= lowbit(t);
}
return sum;
}
struct Node
{
int val;
int pos;
};
bool cmp(Node& lhs, Node& rhs)
{
return lhs.val < rhs.val;
}
Node node[MAXN];
int reflect[MAXN];
int main()
{
#ifdef ONLINE_JUDGE
#else
freopen("D:\\in.txt", "r", stdin);
freopen("D:\\out.txt", "w", stdout);
#endif
while (scanf("%d", &n) != EOF)
{
if (n == 0)
break;
memset(a, 0, sizeof(a));
for (int i = 1; i <=n; i++)
{
scanf("%d", &node[i].val);
node[i].pos = i;
}
sort(node+1, node + n+1, cmp);//注意排序的范围
for (int i = 1; i <= n; i++)
{
//reflect[i] = node[i].pos;
reflect[node[i].pos] = i;//离散化处理,原有序列的排名
}
long long ans(0);
//现在总共有j个数,getsum(a[j])为比a[j]小的数的个数加1,
//则比a[j]大的数的个数为j-getsum(a[j]);
for (int i = 1; i <= n; i++)
{
update(reflect[i], 1);
//ans += (i - getsum(a[i]));
//这个地方要注意理解
ans += (i - getsum(reflect[i]));
}
printf("%lld\n", ans);
}
return 0;
}