P8613 [蓝桥杯 2014 省 B] 小朋友排队

链接

https://www.luogu.com.cn/problem/P8613

思路

归并排序,但是要改一下,原来是统计逆序对,现在对每个元素统计换位多少次,然后用count函数求和即可;

先放i,那么说明j前面的都得和i交换一次,所以从[m+1,j)一共有j-m-1个元素,交换j-m-1次;
先放j,说明i之后的都得和j交换,[i,m]共有m+1-i ;
最后如果i没放完那也同理加上r-m,j没放完就不用换了,直接加在后面。

代码

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define int long long
#define itn long long
#define tin long long
const int N = 1e5 + 10;

struct edge
{
	int begin, val;
};

edge a[N];
edge b[N];
void merge(int l, int m, int r)
{
	int i = l, j = m + 1;
	int cnt = l;
	while (i <= m and j <= r)
	{
		if (a[i].val > a[j].val)
		{
			a[j].begin += m + 1 - i;
			b[cnt++] = a[j++];
		}
		else
		{
			a[i].begin += j -1 - m;//这里改一下
			b[cnt++] = a[i++];
			
		}
	}
	while (i <= m) { a[i].begin += r - m; ; b[cnt++] = a[i++]; }//这里改一下
	while (j <= r)b[cnt++] = a[j++];
	for (itn k = l; k <= r; k++)a[k] = b[k];
	return;
}
void merge_sort(int l, itn r)
{
	if(l<r)
	{
		int m = (l + r) / 2;
		merge_sort(l, m);
		merge_sort(m + 1, r);
		merge(l, m, r);
	}
}
int count(int k)
{
	return (k + 1) * k / 2;
}
void solve()
{
	int n; cin >> n;
	for (int i = 1; i <= n; i++)cin >> a[i].val;
	merge_sort(1, n);
	int ans = 0;
	for (int i = 1; i <= n; i++)
		ans += count(abs(a[i].begin));
	cout << ans;
}
signed main()
{
	IOS;
	solve();
	return 0;
}

posted @ 2025-04-11 09:41  WHUStar  阅读(24)  评论(0)    收藏  举报