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

POJ 2299 Ultra-QuickSort【树状数组+离散化】

2010-07-24 01:19 260 查看
(很久以前写的了,从cppBlog贴过来的)

求逆序对,N个数,N<=500000,一开始没有仔细看题,上来就做,后来才发现数的范围是999999999。因为最多500000个数,所以数和数之间的间隔很大,可以处理一下,使数的间隔变小,然后使用树状数组统计某个数前边的比它大的数的个数。将所有的数放到一个结构体里,称作num,并增加一个成员id,然后按num递增排列,再另开一个数组给每个数重新编号,使数的范围都在N以内。然后就可以很自然的用树状数组做了。当然用归并排序更方便,不过为了练一下树状数组嘛.

#include <cstdio>
#include <cstring>
#include <algorithm>
#define M 500001
using namespace std;
int c[M],aa[M],n;//aa数组为排序后重新编号用
struct digit{
int num,id;
}a[M];
//num为数的大小
bool cmp(digit a,digit b){
return a.numint lowbit(int t){
return t&(t^(t-1));
}
int sum(int t){
int total=0;
while(t>0){
total+=c[t];
t-=lowbit(t);
}
return total;
}
void update(int t,int key){
while(t<=n){
c[t]+=key;
t+=lowbit(t);
}
}
int main()
{
int i,j;
long long ans;
while(scanf("%d",&n),n){
memset(c,0,sizeof(c));
ans=0;
for(i=1;i<=n;i++){
scanf("%d",&a[i].num);
a[i].id=i;
}
sort(a+1,a+n+1,cmp);
aa[a[1].id]=1;         //最小的数编号为1
for(i=2;i<=n;++i){
if(a[a[i].id].num!=a[a[i-1].id].num)
aa[a[i].id]=i;
else
aa[a[i].id]=aa[a[i-1].id];
}
for(i=1;i<=n;++i){
update(a[i],1);
ans+=(sum(n)-sum(aa[i]));
//每次累加该数前边比它大的数的个数
}
printf("%lld/n",ans);
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: