您的位置:首页 > 产品设计 > UI/UE

【树状数组】 poj2299 Ultra-QuickSort

2012-08-19 11:37 429 查看
Ultra-QuickSort

题目:http://poj.org/problem?id=2299

题意:给n个数字,每次只能交换相邻两个数字,问最少需要交换多少次可以将n个数字从小到大排序

题解:可以通过模拟冒泡排序发现,对于每个数字,要把它交换到排序后对应的位置,交换次数就等于它的逆序数,即题目等价于求逆序数。

逆序数定义:在一个排列中,如果一对数的前后位置与大小顺序相反,即前面的数大于后面的数,那么它们就称为一个逆序。一个排列中逆序的总数就称为这个排列的逆序数。

代码:

#include<cstring>
#include<cstdio>
#include<algorithm>
using namespace std;
#define lowbit(x) ((x)&(-(x)))
#define LL long long
LL c[500005],b[500005];//c存和,b存逆序数
int n;
struct node
{
int value,num;
}arr[500005];
bool cmp(node x,node y)
{
return x.value<y.value;
}
LL getsum(int pos)
{
int x=pos;
LL sum=0;
for(;x>0;x-=lowbit(x))
sum+=c[x];
return sum;
}
void update(int pos,int value) //更新pos的值
{
int x=pos;
for(;x<=n;x+=lowbit(x))
c[x]+=value;
}
int main()
{
for(;scanf("%d",&n)&&n;)
{
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++)
{
scanf("%d",&arr[i].value);
arr[i].num=i;
}
sort(arr+1,arr+1+n,cmp);
for(int i=1;i<=n;i++)
{
arr[arr[i].num].value=i;//离散化
}
for(int i=1;i<=n;i++)
{
update(arr[i].value,1);
b[i]=i-getsum(arr[i].value);
}
__int64 ans=0;
for(int i=1;i<=n;++i)
ans+=b[i];
printf("%I64d\n",ans);
}
return 0;
}
来源:http://blog.csdn.net/ACM_Ted
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: