https://vjudge.net/problem/POJ-229
先输入一个数n,再输入n个数,求要交换几次才能使这n个数从小到大输出
求逆序数
c[i] 代表着1 …i 的和 其中 i- c[i] 代表着有i-c[i] 个数 比i 大
树状数组+离散化
0 ≤ a[i] ≤ 999,999,999
存数的时候用 __int64或者long long
#include<iostream>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<string.h>
using namespace std;
const int maxn=500017;
int a[maxn];//离散化后的数组
int c[maxn];//数状数组
int n;
struct node
{
int v;
int order;
} in[maxn];
bool cmp(node a,node b)
{
return a.v<b.v;
}
int lowbit(int i)
{
return i&(-i);
}
void add(int i,int value)
{
while(i<=n)
{
c[i]+=value;
i+=lowbit(i);
}
}
int sum(int i)
{
int ans=0;
while(i>0)
{
ans+=c[i];
i-=lowbit(i);
}
return ans;
}
int main()
{
while(~scanf("%d",&n)&&n)
{
memset(a,0,sizeof(a));
memset(c,0,sizeof(c));
for(int i=1; i<=n; i++)
{
scanf("%d",&in[i].v);
in[i].order=i;
}
sort(in+1,in+n+1,cmp);
for(int i=1; i<=n; i++)
a[in[i].order]=i;
__int64 num=0;
for(int i=1;i<=n;i++)
{
add(a[i],1);
num+=(i-sum(a[i]));
}
printf("%I64d\n",num);
}
}