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个, 所以可以通过求元素在数组中的编号大小进行离散化。
代码如下:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int maxn=500005;
int n;
struct data
{
int dat;
int no;
};
data d[maxn];
int tree [maxn<<2];
//离散化数组
int a[maxn];
void pushup (int re)
{
tree[re]=tree[re<<1]+tree[re<<1|1];
}
//sort函数
int compare (data a,data b)
{
return a.dat<b.dat;
}
void build (int l,int r,int re)
{
tree[re]=0;
if(l==r)
return;
int mid=(l+r)>>1;
build (l,mid,re<<1);
build (mid+1,r,re<<1|1);
}
int query (int l,int r,int re,int left,int right)
{
if(l>=left&&r<=right)
return tree[re];
int ans=0;
int mid=(l+r)>>1;
if(mid>=left)
ans+=query (l,mid,re<<1,left,right);
if(mid<right)
ans+=query (mid+1,r,re<<1|1,left,right);
return ans;
}
void update (int l,int r,int re,int loc)
{
if(l==r)
{
tree[re]++;
return;
}
int mid=(l+r)>>1;
if(loc<=mid)
update (l,mid,re<<1,loc);
else
update (mid+1,r,re<<1|1,loc);
pushup(re);
}
int main()
{
while (scanf("%d",&n)!=EOF&&n)
{
//记录下元素的编号
for (int i=1;i<=n;i++)
{
scanf("%d",&d[i].dat);
d[i].no=i;
}
//排序
sort (d+1,d+n+1,compare);
int num=1;
//离散化
for (int i=1;i<=n;i++)
{
if(i>1&&d[i].dat==d[i-1].dat)
a[d[i].no]=a[d[i-1].no];
else
a[d[i].no]=num++;
}
//建树
build (1,n,1);
long long int sum=0;
for (int i=1;i<=n;i++)
{
sum+=query (1,n,1,a[i]+1,n);
update (1,n,1,a[i]);
}
printf("%lld\n",sum);
}
return 0;
}