【树状数组】 HDOJ 1394 Minimum Inversion Number

树状数组求逆序数问题,每次把最前面的数放到最后面,问最小的逆序数是多少。。注意到题目中数是1-n就比较容易想到解法了,不过如果不是1-n也可以先离散再做。。。先用树状数组求一次初始顺序的,再依次把当前的逆序减去这个数再减1(也就是这个数后面比他小的数的个数),然后加上n减这个数(就是这个数前面比他大的数的个数)。。。最后加上一个输入加速,程序直接跑到第一面了~~~


#include <iostream>
#include <sstream>
#include <algorithm>
#include <vector>
#include <queue>
#include <stack>
#include <map>
#include <set>
#include <bitset>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <climits>
#define maxn 5001
#define eps 1e-6
#define mod 1000000007
#define INF 99999999
#define lowbit(x) (x&(-x))
#define lson o<<1, L, mid
#define rson o<<1 | 1, mid+1, R
typedef long long LL;
using namespace std;

int tree[maxn];
int num[maxn];
int n, tmp;

void add(int x)
{
	for(int i=x;i<=n;i+=lowbit(i)) tree[i]+=1;
}
int sum(int x)
{
	int ans=0;
	for(int i=x;i>0;i-=lowbit(i)) ans+=tree[i];
	return ans;
}
void work(void)
{
	int i, ans=0;
	memset(tree, 0, sizeof tree);
	for(i=n;i>0;i--){
		ans+=sum(num[i]);
		add(num[i]);
	}
	tmp=ans;
}
int get(void)
{
	int temp=0;
	char ch=getchar();
	while(ch>='0' && ch<='9')
		temp=temp*10+ch-'0', ch=getchar();
	return temp+1;
}
int main(void)
{
	int i, mi;
	while(scanf("%d",&n)!=EOF){
		getchar();
		for(i=1;i<=n;i++) num[i]=get();
		work();
		mi=tmp;
		for(i=1;i<n;i++){
			tmp-=num[i]-1;
			tmp+=n-num[i];
			if(tmp<mi) mi=tmp;
		}
		printf("%d\n",mi);
	}
	return 0;
}


你可能感兴趣的:(HDU,树状数组)