题目链接 http://poj.org/problem?id=2299
思路:求n个数组成序列的逆序数,用树状数组优化,由于给出的a[i]的范围很大n较小,所以对数据进行离散化,用结构体记录每个数的值和原始位置p,对序列排序后给每个数一个新的值,这个值的范围为[1,n],这个值只代表一个相对的大小,形成一个新的序列nd[i].原数组的逆序数相当于nd[i]的逆序数。然后就是普通的树状数组求逆序数(nd[i]前面比nd[i]大的数的个数)啦。
data[i].p | 1 | 2 | 3 | 4 | 5 |
data[i].v | 9 | 1 | 0 | 5 | 4 |
排序后的位置即新值 | 5 | 2 | 1 | 4 | 3 |
nd[[i] | 5 | 2 | 1 | 4 | 3 |
#include<cstdio>
#include<algorithm>
using namespace std;
const int num=500005;
struct node
{
int v,p;
}data[num];
int c[num],n,nd[num];
bool cmp(const node &a,const node &b)
{
return a.v<b.v;
}
int lowbit(int a)
{
return a&(-a);
}
void updata(int a,int add)
{
while(a<=n)
{
c[a]+=add;
a+=lowbit(a);
}
}
int sum(int a)
{
int s=0;
while(a>0)
{
s+=c[a];
a-=lowbit(a);
}
return s;
}
int main()
{
int i;
__int64 ans;
//freopen("in.txt","r",stdin);
while(scanf("%d",&n)!=EOF)
{
if(n==0)
break;
for(i=1;i<=n;i++)
{
scanf("%d",&data[i].v);
data[i].p=i;
}
sort(data+1,data+1+n,cmp);
for(i=1;i<=n;i++)
c[i]=0;
for(i=1;i<=n;i++)
nd[data[i].p]=i;
ans=0;
for(i=1;i<=n;i++)
{
updata(nd[i],1);
ans+=(__int64)(sum(n)-sum(nd[i]));
}
printf("%I64d\n",ans);
}
return 0;
}