並べ替えを行い、逆順対数を求める(他の2つの姿勢BIT線分樹を添付)


逆順の3つの方法を求めて、ツリーの配列の線分の木を並べ替えます.
交換回数は逆順対数となります.
poj 1804データ範囲が小さいので、intはオーバーフローしません.spojにはlong long longが必要です.(spojに登録すると、検証コードを取得する時にGoogleに訪問するので、必要です.)
#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
const int maxn = 2e5 + 7;
int a[maxn], b[maxn];
long long cnt;
//         cnt      , 1   。 ary[l:r]  ,     ,ary = des
void merge_sort(int ary[], int l, int r, int des[]) { // ary[l..r]       
	if (l >= r) return;
	int mid = (l + r) >> 1;
	merge_sort(ary, l, mid, des);
	merge_sort(ary, mid + 1, r, des);
	int i = l, j = mid + 1, cur = l; //     
	while (i <= mid && j <= r) {
		if (ary[i] <= ary[j]) {
			des[cur++] = ary[i++];
		}			
		else { //   ,ary[i] > ary[j], ary[j]    ( ) 
			des[cur++] = ary[j++];
			cnt += mid - i + 1; //     
			// ary[i] > ary[j] ,       ary[i]     ary[j] , ary[j]  ary[i]    ,      mid + 1 - i
		}
	}
	while (i <= mid) {
		des[cur++] = ary[i++];
	}
	while (j <= r) {
		des[cur++] = ary[j++];
	}
	memcpy(ary + l, des + l, sizeof(int) * (r - l + 1));
} 

int main()
{
	int T;
	scanf("%d", &T);
	for (int k = 1; k <= T; ++k) {
		int n;
		scanf("%d", &n);
		cnt = 0;
		for (int i = 0; i < n; ++i)
			scanf("%d", a + i);
		merge_sort(a, 0, n - 1, b);
		//printf("%d", b[0]);
		//for (int i = 1; i < n; ++i)
		//	printf(" %d", b[i]);
		//puts(""); //          
		//printf("Scenario #%d:
%d

", k, cnt); //poj1804 ,poj ,int printf("%lld
", cnt); //http://www.spoj.com/problems/INVCNT/en/ } return 0; }
BIT解法(POJ 1804に適用)
#include 
#include 
#define ADD 1000001
#define M 2000001
#define N 1007 
using namespace std;
int ary[N], bit[M + 1], n;
int lowbit(int x) {
	return x & (-x);
}
void add(int pos, int val) {
	while(pos <= M) { //pos <= ?
		bit[pos] += val;
		pos += lowbit(pos);
	}
}

int sum(int pos) { //  1:pos   
	int res = 0;
	while(pos > 0) {
		res += bit[pos];
		pos -= lowbit(pos);
	}
	return res;
}

int main() {
	int T, kase = 0;
	scanf("%d", &T);
	while (T-- > 0) {
		memset(bit, 0, sizeof bit);
		scanf("%d", &n);
		long long ans = 0; 
		for (int i = 0; i < n; ++i) {
			scanf("%d", ary + i);
			ary[i] += ADD;
			ans += (i - sum(ary[i])); //       
			add(ary[i], 1);
		}
		printf("Scenario #%d:
%lld

", ++kase, ans); } return 0; }
hdu 1394
#define _CRT_SECURE_NO_WARNINGS
#include 
#include 
#include 
using namespace std;
const int N = 5007;
int segTree[N << 1], ary[N];
void build(int rt, int l, int r) {
	segTree[rt] = 0;
	if (l == r) return;
	int mid = l + r >> 1;
	build(rt << 1, l, mid);
	build(rt << 1 | 1, mid + 1, r);
}
void update(int rt, int l, int r, int pos) {
	if (l == r) {
		segTree[rt]++; //       ,   1
		return;
	}
	int mid = l + r >> 1;
	if (pos <= mid)
		update(rt << 1, l, mid, pos);
	else update(rt << 1 | 1, mid + 1, r, pos);
	segTree[rt] = segTree[rt << 1] + segTree[rt << 1 | 1]; //        
}
int query(int rt, int l, int r, int L, int R) {
	if (L <= l && r <= R) {
		return segTree[rt];
	}
	int mid = l + r >> 1, res = 0;
	if (L <= mid)
		res += query(rt << 1, l, mid, L, R);
	if (R > mid)
		res += query(rt << 1 | 1, mid + 1, r, L, R);
	return res;
}
int main()
{
	int n;
	while (~scanf("%d", &n)) {
		memset(segTree, 0, sizeof segTree);
		int cnt = 0;
		for (int i = 0; i < n; ++i) {
			scanf("%d", ary + i);
			cnt += query(1, 0, n - 1, ary[i], n - 1);
			update(1, 0, n - 1, ary[i]); //    
		}
		int minCnt = cnt;
		for (int i = 0; i < n; ++i) {
			cnt += n - ary[i] - ary[i] - 1; //                     ,     ary[i] 0:n-1     
			minCnt = min(minCnt, cnt);
		}
		printf("%d
", minCnt); } return 0; }