Aizu - ALDS1_5_D The Number of Inversions 【归并思路求逆序数】

版权声明:如需转载,记得标识出处 https://blog.csdn.net/godleaf/article/details/82930224

题目链接:https://vjudge.net/problem/Aizu-ALDS1_5_D

思路:(挑战程序设计(算法与数据结构))

需要特别注意的有两点:1 在Left和Right数组中的末尾要加一个INF,保证其中一个数组为空时,另一个数组能继续把数填进A数组中;2 二分中 L和R的取值;

#include <iostream>
#include <cstdio>
#include <cstring>

using namespace std;

typedef long long ll;

const int Maxn = 2e5+10;

int a[Maxn],Left[Maxn/2],Right[Maxn/2];

ll merge (int A[], int mid, int L, int R);

ll solve (int A[], int L, int R) {
	int mid; ll ans1,ans2,ans3;
	if (L < R) {
		mid = (L+R)/2;
		ans1 = solve (A, L, mid);
		ans2 = solve (A, mid+1, R);
		ans3 = merge (A, mid, L, R);
		return ans1+ans2+ans3;
	} else return 0;
}

ll merge (int A[], int mid, int L, int R) {
	int n1 = mid-L+1;
	int n2 = R-(mid+1)+1;
	for (int i = 0; i < n1; ++i) Left[i] = A[L+i];
	for (int i = 0; i < n2; ++i) Right[i] = A[mid+1+i];
	Left[n1] = Right[n2] = 1e9+10;  // 当有左右的数组中的有意义的数为空时,要保证最后一个数比另一个数组所有的数都大, 
	ll ans = 0;						// 才能保证把所有的数都放进A数组中
	int i, j; i = j = 0;
	while (L <= R) {
		if(Left[i] <= Right[j]) {
			A[L++] = Left[i++];
		} else {
			ans+=n1-i;
			A[L++] = Right[j++];
		}
	}
	return ans;
}

int main (void)
{
	int n;
	cin >> n;
	for (int i = 0; i < n; ++i) cin >> a[i];
	ll ans = solve (a, 0, n-1);
	cout << ans << endl;
	return 0;
}

猜你喜欢

转载自blog.csdn.net/godleaf/article/details/82930224