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

本文介绍了一种使用归并排序算法求解逆序对数量的方法,通过将数组分为左、右两部分,分别求解左右部分的逆序对数量,再通过归并过程求解跨部分的逆序对数量。在归并过程中,通过对左右两个临时数组的比较,实现了逆序对的计数,并确保了最终数组的有序性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接: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;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值