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

poj_2299 Ultra-QuickSort

2013-09-09 16:56 260 查看
原题链接:http://poj.org/problem?id=2299

分析:树状数组求逆序对+离散化。

       1:因为“n distinct integers”,所以不会有重复的数,可以用hash的方式让数与下标一一对应。如题中样例。

        输入的数    : 9 1 0 5 4

        排序后的数: 0 1 4 5 9

       对应的下标:  1 2 3 4 5

      因为n < 500000,通过这样子的处理就可以使0 ≤ a[i] ≤ 999999999,最大下标为500000。。这就是离散化。

    2:接着是树状数组求逆序对,我们从数组的后面开始插入到数组,那么数的逆序就是在之前插入的比它小的数,统计输出就好。

我的代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
#define MAXN 500005
int C[MAXN];
int n;
int a[MAXN],b[MAXN];
void add(int i)
{
for(;i<=n;i+=i&(-i)) C[i]+=1;
}
int get_sum(int i)
{
int sum=0;
for(;i>0;i-=i&(-i)) sum+=C[i];
return sum;

}
int ser(int x)
{
int l=1,r=n;
while(l<=r)
{
int mid=(l+r)>>1;
if(b[mid]==x) return mid;
else if(b[mid]>x) r=mid-1;
else l=mid+1;
}

}
int main()
{
while(scanf("%d",&n)!=EOF&&n)
{
memset(C,0,sizeof(C));
for(int i=1;i<=n;i++) scanf("%d",a+i);
memcpy(b,a,sizeof(a));
sort(b+1,b+1+n);
LL ans=0;
for(int i=n;i>=1;i--)
{//从数组的画面插数进树状数组,这样就可以找比它找插,且小得数有几个。
int ind=ser(a[i]); //有种hash的感觉,数与下标一一对应。
ans+= get_sum(ind); //得到有几个比ind小的数。
add(ind);
}
printf("%lld\n",ans);

}
return 0;
}


总结:第一次交,WA了,想了下,n最大是500000,在最坏情况下,所有的数都交换则需,n*(n+1)/2次,用int的话就溢出了,改为long long 。

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: