HDU2689 Sort it【树状数组】【逆序数】
原创
©著作权归作者所有:来自51CTO博客作者ITCharge的原创作品,请联系作者获取转载授权,否则将追究法律责任
题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=2689
题目大意:
求把一个具有N个不同元素的序列通过交换两个相邻的元素转换成升序序列需要进行的交换次数
是多少。
例如:1 2 3 5 4,只需要交换5和4,交换次数为1次。
思路:
典型的求逆序数题。其实可以直接暴力过。但是用树状数组效率比较高。对于值为a第i个元素,
需要交换次数为前i个元素中大于a的元素个数,即逆序数。
用树状数组来做,数组Tree[i]表示数字i是否在序列中出现过,如果数字i已经存在于序列中,
Tree[i] = 1,否则Tree[i] = 0。按序列从左到右将值为a的元素当作下标为a,赋值为1插入树状
数组里,这时,比a的数个数就是i - Query(a)。将全部结果累加起来就是逆序数了。
AC代码:
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
using namespace std;
const int MAXN = 100010;
int N,Tree[MAXN];
int Lowbit(int i)
{
return i & (-i);
}
void Update(int i,int x)
{
while(i <= N)
{
Tree[i] = Tree[i] + x;
i = i + Lowbit(i);
}
}
int Query(int n)
{
int sum = 0;
while(n > 0)
{
sum += Tree[n];
n = n - Lowbit(n);
}
return sum;
}
int main()
{
while(cin >> N && N)
{
int a,ans = 0;
memset(Tree,0,sizeof(Tree));
for(int i = 1; i <= N; ++i)
{
cin >> a;
Update(a,1);
ans += i - Query(a);
}
cout << ans << endl;
}
return 0;
}