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.
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
题目大体意思就是说给定一组数据,求把这组数据排列成有序数组的交换次数,除了可以用数据结构里面提到的归并排序,也可以用线段树,但是在用线段树的时候有一点一定要注意,就是数据必须要离散化,题目里给出了这样两个限制,输入的数据量小于500000,每个数据小于999999999,也就是说,如果不进行离散化,构建线段树的时候就需要999999999<<2个节点,远超出程序的内存限制,所以只能进行离散化,将节点数缩小到500000<<2的范围内,这样就可以使程序在合理范围内。
离散化大体过程:先将数据和编号存在一个结构体数组中,对这个数组进行sort排序,排序后把名次对应存在另外一个数组里,这样就能够实现将过长数据转化为离散数据的过程,在线段树查询的时候直接使用名次来代替原始数据。
AC代码
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<memory.h>
using namespace std;
struct Node {
int l,r,num;
};
struct Num{
int id,num;
};
struct Num N[500005];
struct Node node[500005<<2];
int b[500005];
void build(int x,int y,int m)
{
node[m].l=x;
node[m].r=y;
node[m].num=0;
if(x==y) return;
int mid=(x+y)/2;
build(x,mid,m<<1);
build(mid+1,y,m<<1|1);
node[m].num=node[m<<1].num+node[m<<1|1].num;
}
void update(int tar,int m)
{
if(node[m].l==tar&&node[m].r==tar)
{
node[m].num++;
return;
}
int mid=(node[m].l+node[m].r)/2;
if(tar<=mid) update(tar,m<<1);
else update(tar,m<<1|1);
node[m].num=node[m<<1].num+node[m<<1|1].num;
}
int query(int x,int y,int m)
{
if(node[m].l==x&&node[m].r==y)
return node[m].num;
int mid=(node[m].l+node[m].r)/2;
if(y<=mid)
return query(x,y,m<<1);
else if(x>mid)
return query(x,y,m<<1|1);
else
return query(x,mid,m<<1)+query(mid+1,y,m<<1|1);
}
bool cmp(struct Num x,struct Num y)
{
return x.num<y.num;
}
int main()
{
int n;
while(scanf("%d",&n)&&n)
{
build(0,n+1,1);
memset(b,0,sizeof(b));
long long int ans=0;
for(int i=0;i<n;i++)
{
cin>>N[i].num;
N[i].id=i;
}
sort(N,N+n,cmp);
for(int i=0;i<n;i++)
b[N[i].id]=i+1;
for(int i=0;i<n;i++)
{
ans+=query(b[i]+1,n+1,1);
update(b[i],1);
}
cout<<ans<<endl;
}
return 0;
}