【归并排序】奶牛的图片(jzoj 1812)
程序员文章站
2022-05-10 15:11:55
...
奶牛的图片
jzoj 1812
题目大意
给你一个序列,你可以交换相邻的两个数
让你用最少的交换次数来使得这个序列变成形如的序列
问你最少的交换次数是多少次
输入样例
5
3
5
4
2
1
输出样例
2
解题思路
如果我们变成所需次数就是他的逆序对(证明上网找)
如果我们把1放到n后面,那逆序对就要减去1原来的贡献再加上1现在的贡献
就是,然后枚举每一种情况,求最小解
注:是指的初始位置
代码
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define ll long long
using namespace std;
ll n, g, ans, a[100010], b[100010], s[100010];
void work(ll l, ll r)//归并排序求逆序对
{
if (l >= r) return;
ll mid = (l + r) / 2;
ll L = l, R = mid + 1;
work(l, mid);
work(mid + 1, r);
for (ll i = l; i <= r; ++i)
{
if ((a[L] < a[R] || R > r) && L <= mid) b[i] = a[L++];
else
{
b[i] = a[R++];
g += mid - L + 1;
}
}
for (ll i = l; i <= r; ++i)
a[i] = b[i];
return;
}
int main()
{
scanf("%lld", &n);
for (ll i = 1; i <= n; ++i)
{
scanf("%lld", &a[i]);
s[a[i]] = i;
}
work(1, n);
ans = g;
for (ll i = 1; i < n; ++i)
{
g = g - (s[i] - 1) + (n - s[i]);//把当前的第一个数放到最后
ans = min(ans, g);
}
printf("%lld", ans);
return 0;
}
下一篇: 归并排序模板(附求逆序对)