H. Maximizer

该博客讨论了如何通过最少的相邻交换次数调整排列A,以使它与排列B的每个位置差的绝对值之和达到最大。当n为偶数时,[1, n/2]可以与[n/2+1, n]任意对应,对于奇数n,n/2+1可以在两侧分配。计算移动次数的方法是从左到右计算差的绝对值之和,整个过程可在O(n)时间内完成。" 132220357,19687568,FPGA设计:parameter与localparam的区别,"['FPGA开发', '硬件描述语言']

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

https://codeforces.com/group/5yyKg9gx7m/contest/280318/problem/H
题意:给定n的排列,A和B,求A的最少相邻交换次数,使得A和B每个位置差的绝对值之和最大。
思路: i i i对应 n + 1 − i n+1-i n+1i是一种,另外,如果n是偶数,则 [ 1 , n / 2 ] [1,n/2] [1,n/2] [ n / 2 + 1 , n ] [n/2+1,n] [n/2+1,n]任意对应都行,若n为奇数, n / 2 + 1 n/2+1 n/2+1分到左右边都可以,取较小的。
移动次数的话,按坐标从左到右依次取差的绝对值之和即可。 O ( n ) O(n) O(n)

#include<bits/stdc++.h>
using namespace std;
const int maxn=250000+100;
typedef pair<int,int> P;
typedef long long ll;
#define MP(a,b) make_pair(a,b)

int n,a[maxn],b[maxn];

int main()
{
//	freopen("input.in","r",stdin);
	cin>>n;
	for(int i=1;i<=n;i++)scanf("%d",&a[i]);
	for(int i=1;i<=n;i++)scanf("%d",&b[i]);
	if(!(n&1))
	{
		ll s=0;
		vector<int> A,B;
		for(int i=1;i<=n;i++)if(a[i]<=n/2)A.push_back(i);
		for(int i=1;i<=n;i++)if(b[i]>n/2)B.push_back(i);
		for(int i=0;i<A.size();i++)s+=abs(A[i]-B[i]);
		cout<<s;
	}
	else
	{
		ll s1=0,s2=0;
		vector<int> A,B;
		for(int i=1;i<=n;i++)if(a[i]<=n/2)A.push_back(i);
		for(int i=1;i<=n;i++)if(b[i]>n/2+1)B.push_back(i);
		for(int i=0;i<A.size();i++)s1+=abs(A[i]-B[i]);
		A.clear();B.clear();
		for(int i=1;i<=n;i++)if(a[i]<=n/2+1)A.push_back(i);
		for(int i=1;i<=n;i++)if(b[i]>n/2)B.push_back(i);
		for(int i=0;i<A.size();i++)s2+=abs(A[i]-B[i]);
		cout<<min(s1,s2);
	}
	return 0;
}
 
 
 
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值