/*************************************
题目大意:给你1——n之间的数,组成的一串数;求出这组数的逆序数(所谓逆序就是比i小的数排在i的后面);
题目解析:运用树状数组动态的对上更新tree[ ] 数组,对下统计getsum[ ]数组,每更新一次都计算出getsum(n)-getsum(x) --------(此时的getsum(n)-getsum(x)表示的时x之前比x大的数的个数,它与逆序的定义相似),并合计所有做差的和;
错误分析:1.要先统计getsum(n)-getsum(x),再更新数据,计算出X之前比X大的数的个数;
2.tree[ ]数组初始化应为0;此时的update(x,val),val=1;
3.tree[i]表示A[i-2^k+1]到A[i]的和,此时A[ ]数组初始化为0;getsum[ ]表示A[1]到A[i]的和;
**************************/
#include<cstdio>
#include<iostream>
#include<cstring>
#define MAX 1005
using namespace std;
int n,tree[MAX];
int lowbit(int x)
//分离出后面的1;(如3:十进制3&-3=1 二进制11&01=1 (以补码形式计算) 4: 十进制4&-4=4 二进制100&100=100)
{
return x&-x;
}
void update(int x,int val)
//更新数据,数组tree[ ]对上更新;
{
while(x<=n)
{
tree[x]+=val;
x+=lowbit(x);
}
}
int getsum(int x)
//统计前x个数的和,对下更新
{
int sum=0;
while(x>0)
{
sum+=tree[x];
/*如x=13,二进制为1101 ,则经过lowbit (),可得1100,1000
于是getsum[1101]=tree[1101]+tree[1100]+tree[1000]*/
x-=lowbit(x);
}
return sum;
}
int main()
{
int i,x;
long long s;
while(scanf("%d",&n)!=EOF)
{
memset(tree,0,sizeof(tree));
s=0;
for(i=1;i<=n;i++)
{
scanf("%d",&x);
s+=getsum(n)-getsum(x);
//每输入一个数(即更新一次)则计算出它前面比它大的数;
update(x,1);
//更新数据
}
printf("%lld\n",s);
}
return 0;
}