专栏文章

P1908 逆序对

P1908题解参与者 1已保存评论 0

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
0 条
当前快照
1 份
快照标识符
@mip4quwg
此快照首次捕获于
2025/12/03 06:08
3 个月前
此快照最后确认于
2025/12/03 06:08
3 个月前
查看原文
CPP
//本题用归并排序来写,大概是用O(n log n)的时间复杂度 
#include <iostream>

using namespace std;

const int N = 5e5 + 5;

long long n,a[N],b[N],ans;//a[i]存要排序的数组,b[i]作为中转,把已经排好序了的值再赋给a[i],ans存答案 
//记得开 long long ans会爆int 
void merge (int l,int r) {//归并排序板子 
	
	if ((r - l) == 0) return ;//如果说这个区间的长度为1了就不需要继续往下分了,返回上一层 
	
	int mid = (l + r) / 2;//二分,以mid作为边界值 
	int i = l,j = mid + 1,cnt = l;//i为了不影响l值的变化而新开的一个变量,j取第二个区间的边界值,cnt存排序的长度 
	
	merge (l,mid);//让第一个区间进行二分,使得它变有序 
	merge (mid + 1,r);//同第一个一样 
	
	while (i <= mid && j <= r) {//遍历完这两个区间共同有的长度 
		
		if (a[i] <= a[j]) {//如果说第一个区间的最小值小于第二个区间的最小值,就把它加进b数组 
			b[cnt ++] = a[i];//加入数组 
			i ++;//跳到第一个序列的第二个元素 
		} else {//所以答案就加第一个区间的长度 
			ans += mid - i + 1;//因为如果他比第一个区间的最小值要小的话,那么说明第一个区间的所有数都比他大,又因为第一个区间的数都在他前面,所以都构成逆序对 
			b[cnt ++] = a[j];//同上 
			j ++;//更新元素 
		}
	}
	
	for (i ;i <= mid;i ++) b[cnt ++] = a[i];//如果说第一个区间还剩余元素没加,直接全加进去 
	for (j ;j <= r; j ++) b[cnt ++] = a[j];//同上 
	for (int k = l;k <= r;k ++) a[k] = b[k];//最后再赋给a数组已经排好序了的值 
	
}

int main () {
	
	cin >> n;
	
	for (int i = 1;i <= n;i ++) cin >> a[i];
	
	merge (1,n);//归并排序 
	
//	for (int i = 1;i <= n;i ++) {
//		cout << b[i] << '\n';
//	}
	
	cout << ans << '\n';//输出答案 
	return 0;//华丽结束 
}

评论

0 条评论,欢迎与作者交流。

正在加载评论...