传送门:http://acm.hdu.edu.cn/showproblem.php?pid=2689
代码如下:
#include <iostream>
#include <stdio.h>
#include <string.h>
#define maxn 10000
using namespace std;
int n,tree[maxn];
int lowbit(int i)
{
return i&(-i);
}
int update(int i,int x)
{
while(i<=n)
{
tree[i]=tree[i]+x;
i=i+lowbit(i);
}
return 0;
}
int query(int n)
{
int sum=0;
while(n>0)
{
sum+=tree[n];
n=n-lowbit(n);
}
return sum;
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
int a,ans=0;
memset(tree,0,sizeof(tree));
for(int i=1;i<=n;i++)
{
scanf("%d",&a);
update(a,1);
ans+=(i-query(a));
/*
query(a)查询得到的是当前小于等于a的数字的个数,
i是已插入数字的个数,两数相减的到的即是a的逆序数;
例如:{4,3,2,1}
1.输入4,调用update(4,1),把第4位设置为1
1 2 3 4
0 0 0 1
计算1-4上比小于等于4的数字的个数,即query(4)=1,
1-query(4)=0 就可以得到对于4的逆序数为0。
2.输入3调用update(3,1),把第3位设置为1
1 2 3 4
0 0 1 1
计算1-3上比小于等于3的数字的个数,即query(3)=1,
2-query(3)=1,就可以得到对于3的逆序数为1。
3.输入2,调用update(2,1),把第2位设置为1
1 2 3 4
0 1 1 1
计算1-2上比小于等于2的数字的个数,即query(2)=1,
3-query(2)=2,就可以得到对于2的逆序数为2。
4.输入1,调用update(1,1),把第1位设置为1
1 2 3 4
1 1 1 1
计算1-1上比小于等于1的数字的个数,即query(1)=1,
4-query(1)=3,就可以得到对于1的逆序数为3。
注意:这里忽略了update函数对父节点的更新,但实际上是一样的,父节点代表区间和。
*/
}
printf("%d\n",ans);
}
return 0;
}