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;
}

浙公网安备 33010602011771号