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

poj 2299 Ultra-QuickSort

2013-01-18 18:56 260 查看
题目:http://poj.org/problem?id=2299

一开始敲了一个冒泡,但是一看数据范围很大,会超时,然后想了想也没想出来什么好的方法,搜了一下解题报告,是逆序数的问题,线代学的不好,都忘了,搜了一下,用的是归并,还有一个方法是树状数组,没接触过树状数组,所以有了解了一下树状数组

归并:

在合并的过程中是将两个相邻并且有序的序列合并成一个有序序列,如以下两个有序序列

Seq1:3 4 5

Seq2:2 6 8 9

合并成一个有序序:

Seq:2 3 4 5 6 8 9

对于序列seq1中的某个数a[i],序列seq2中的某个数a[j],如果a[i]<a[j],没有逆序数,如果a[i]>a[j],那么逆序数为seq1中a[i]后边元素的个数(包括a[i]),即len1-i+1,

这样累加每次递归过程的逆序数,在完成整个递归过程之后,最后的累加和就是逆序的总数

注:要用__int64,long和long long会wa

代码:

View Code

#include <iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
struct node
{
__int64 data;
__int64 pos;
}su[500010];
int tree[500010];
__int64 num;
__int64 n;

__int64 lowbit(__int64 num)
{
return num&(num^(num-1));
}

__int64 sum(__int64 pos)
{
__int64 ans=0;
while(pos>0)
{
ans+=tree[pos];
pos-=lowbit(pos);
}
return ans;
}
void update(__int64 pos)
{
while(pos<=n)
{
tree[pos]++;
pos+=lowbit(pos);
}
}
bool cmp(node a,node b)
{
return a.data>b.data;
}
int main()
{

while(scanf("%I64d",&n)!=EOF)
{
if(n==0)
break;
int i;
for(i=1;i<=n;i++)
{
scanf("%I64d",&su[i].data);
su[i].pos=i;
}
sort(su+1,su+n+1,cmp);
num=0;
memset(tree,0,sizeof(tree));
for(i=1;i<=n;i++)
{
num+=sum(su[i].pos);
update(su[i].pos);
}
printf("%I64d\n",num);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: