题目链接:
http://acm.hdu.edu.cn/showproblem.php?pid=1394
题解:
利用树状数组搞一搞逆序数就好了,这题不需要离散化
AC代码:
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
int tree[5005],LEN;
int lowbit(int i)
{
return i&( -i);
}
void add(int k, int i)
{
while(k <= LEN)
{
tree[k] += i;
k += lowbit(k);
}
}
int sum(int k)
{
int re = 0;
while(k > 0)
{
re += tree[k];
k -= lowbit(k);
}
return re;
}
int main()
{
int ans;
int number[5005] = {0};
while(cin >> LEN)
{
memset(tree,0,sizeof(tree));
for(int i = 0; i < LEN; i++)
scanf("%d", &number[i]);
int ct1 = 0,ct2 = 0;
for(int i = 0; i < LEN; i ++)
{
ct1 += sum(LEN - number[i]);//sum(LEN - number[i])即是number[i]的逆序数
cout << sum(LEN - number[i]) << " ";
add(LEN - number[i],1);//按从大到小的顺序加数排列,这样树状数组的前几项的和就是逆序数了
}
ans = ct1;
cout << ans <<endl;
//for(int i = 1; i <= LEN; i++)
// cout << sum(i) <<endl;
for(int i = 0; i < LEN-1; i++)
{
ct2 = ct1;//新的逆序数 = 前一个逆序数
add(LEN - number[i], -1);
ct2 = ct2 + sum(LEN - number[i]) - number[i];//数学问题,sum2 = sum1 + 取出的数的逆序数 - 取出的数
add(LEN - number[i], 1);
// cout << ct2 <<endl;
if(ans > ct2)
ans = ct2;
ct1 = ct2;//新的逆序数
}
printf("%d\n", ans);
}
return 0;
}