Codeforces Round #743 (Div. 2) B. Swaps

原题链接
在这里插入图片描述
在这里插入图片描述

题目大意:

给定两个数组 a a a b b b a a a 数组是 1~2n 当中的所有 奇数 的一个排列, b b b 数组是1~2n当中 偶数 的一个排列,现在你可以做如下操作:

  • 选择两个序列中的任意一个
  • 选择一个位置 i ( 1 ≤ i ≤ n − 1 ) i(1≤i≤n-1) i(1in1),交换 i i i i + 1 i+1 i+1 位置上的数字

计算将 a a a 序列的第一个数小于 b b b 序列的第一个数的最少操作次数。 1 ≤ n ≤ 1 e 5 1≤n≤1e5 1n1e5

解题思路:

有三种情况:

  1. 第一种情况,只需要交换 a a a 序列就好了,将第一个小于 b b b 开头元素的交换头部就可以了。
  2. 第二种情况,只需要交换 b b b 序列就好了,将第一个大于 a a a 开头元素的元素交换到头部就好了。
  3. 第三种情况, a b a\quad b ab 序列都要移动。

首先,在 b b b 数组中记录大于等于bi的最近的位置。
这样,我们就可以遍历 a a a 数组,找到对于每个 a i ai ai 来说,相对于b第一个大于 a i ai ai 的元素的位置,然后两个加在一起就是我们需要交换的次数,我们只要遍历的时候不断地取最小值就好了。

关键点在于mp数组的求解:
举个栗子模拟一下:

b数组286410
mp数组初始化12345
mp数组更新12225

在手动模拟的过程中发现,从大往小更新,那么可以更新到大于等于 b i b_i bi 的所有数字中位置最靠前的那个位置。

代码:

#include <bits/stdc++.h>
#include <iostream>
#include <string.h>
#include <algorithm>
#define ll long long
#define qc ios::sync_with_stdio(false); cin.tie(0);cout.tie(0)
using namespace std;
const int MAXN = 2e5 + 7;
const int inf = 0x3f3f3f3f;
const ll INF = 0x3f3f3f3f3f3f3f3f;
int a[MAXN],b[MAXN],mp[MAXN];

int main()
{
//	freopen("in.txt", "r", stdin);
	qc;
	int t;
	cin>>t;
	while(t--)
	{
		int n;
		cin>>n;
		for(int i=1;i<=n;i++)
			cin>>a[i];
		for(int i=1;i<=n;i++)
		{
			cin>>b[i];
			mp[b[i]]=i;
		}
		for(int i=2*n-2;i>=2;i-=2)
			mp[i]=min(mp[i],mp[i+2]);
		int ans=inf;
		for(int i=1;i<=n;i++)
			ans=min(ans,mp[a[i]+1]+i-1);
		cout<<ans-1<<endl;
	}
	return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值