Ultra-QuickSort
Time Limit: 7000MS | Memory Limit: 65536K | |
Total Submissions: 34679 | Accepted: 12466 |
Description
![](https://i-blog.csdnimg.cn/blog_migrate/b3530eaa8fa98ef394d3639722240a8c.jpeg)
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
本题给定一个序列,要求相邻的数交换多少次后可以得到一个递增的序列。这个题的过程似曾相识,仔细想了想,原来是冒泡排序的基本过程思想。冒泡模拟,肯定会超时的,冒泡的时间复杂度为O(N*N)。我们可以这样想,我们先把最大的移到最后,然后是次大的……这样一来就变了了我们熟悉的模型,求该序列的逆序数了。求逆序数是经典的线段树的用法。
这里说说求逆序数的线段树的做法。先把序列离散化,即从小到大排序,序号与数列中的数对应,然后按序列原有的顺序依次统计每个数的对应的逆序数,并修改线段树。具体做法是先查询线段数中比它大且排在它前面的数,对应区间为当前到末尾的区间和;然后再对应位置插入该数,即将对应位置修改为1.下面使用树状数组实现的:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN=500000+100;
int da[MAXN];
int tda[MAXN];
//**********************************************
int C[MAXN];
int Lowbit[MAXN];
//C[i] = a[i-lowbit(i)+1] + …+ a[i],下表从1开始
//Lowbit[i]=i&(i^(i-1));或Lowbit[i]=i&(-i);
//1.查询
int QuerySum(int p)
//查询原数组中下标1-p的元素的和
{
int nSum=0;
while(p>0)
{
nSum+=C[p];
p-=Lowbit[p];
}
return nSum;
}
//2.修改+初始化
void Modify(int p,int val)
//原数组中下表为p的元素+val,导致C[]数组中部分元素值的改变
{
while(p<=MAXN-10)
{
C[p]+=val;
p+=Lowbit[p];
}
}
//************************************************************
bool cmp(int a,int b)
{
return a<b;
}
int Binary_research(int tmp,int n)
{
int mid,low=1,high=n;
while(low<=high)
{
mid=(low+high)>>1;
if(tda[mid]<=tmp)low=mid+1;
else high=mid-1;
}
return high;
}
int main()
{
int n,i;
__int64 ans;
for(i=1;i<MAXN;i++)
Lowbit[i]=i&(-i);
while(~scanf("%d",&n),n)
{
for(i=1;i<=n;i++)
{
scanf("%d",&da[i]);
tda[i]=da[i];
}
sort(tda+1,tda+n+1,cmp);
memset(C,0,sizeof(C));
ans=0;
for(i=1;i<=n;i++)
{
int id=Binary_research(da[i],n);
ans+=(__int64)(QuerySum(n)-QuerySum(id));
Modify(id,1);
}
printf("%I64d\n",ans);
}
return 0;
}