http://poj.org/problem?id=2299
其實就是求次序列的逆序數,但是這道題目要注意到,0 ≤ a[i] ≤ 999,999,999 ,用樹狀數組做的時候,開不了這麼大的數組,但是 n < 500,000,我們可以用離散化的思想,用一個較小的範圍的數組來解決數據量過大的問題。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include<algorithm>
using namespace std;
int b[500010],c[500010],d[500010],n,maxx;
struct A
{
int x,index;
}a[500010];
int cmp(A p1,A p2)
{
return p1.x < p2.x;
}
int lowbit(int x)
{
return x & (-x);
}
void update(int x,int y)
{
while(x <= n)
{
c[x] += y;
x += lowbit(x);
}
}
int getsum(int x)
{
int tmp = x;
int res = 0;
while(x > 0)
{
res += c[x];
x -= lowbit(x);
}
return res;
}
int main()
{
while(~scanf("%d",&n),n)
{
memset(b,0,sizeof(b));
memset(c,0,sizeof(c));
memset(d,0,sizeof(d));
int i,j,num;
maxx = 0;
for(i = 1; i <= n;i++)// 離散化
{
scanf("%d",&a[i].x);
a[i].index = i;
}
sort(a+1,a+n+1,cmp);
for(i = 1; i <= n; i++)
b[a[i].index] = i;
for(i = 1; i <= n; i++)//getsum 函數求出的是 b[i] 前面出現的比他小的數的個數
{
d[i] = i-1 - getsum(b[i]);
update(b[i],1);
}
long long res = 0;
for(i = 1; i <= n; i++)// 求出所有的逆序數。注意有可能超出int
res += d[i];
printf("%I64d\n",res);
}
return 0;
}