CF1898D题解

题目回顾

两个长度均为 n 的数组 a,b一次操作可以选择两个下标 i,j,交换bi​,bj​。你需要进行最多一次操作,最大化 \sum_{i=1}^{n}\left | ai-bi \right |

看到两个数之差的绝对值时,那必须想到两个点之间的距离啊(其实我也是想了很久才想到,我是不是要回七年级重修了嘤嘤嘤)

那么这题就从数学问题变成了几何问题,就是给一堆端点让你求线段长最值,但你可以将两条线段的端点互换,那么互换端点有什么性质么?

第一种情况之前的两条线段相离如图所示

很明显看出改完后比改之前多了2 * \left |l2 - r1 \right | 

第二种情况:两条线段有公共部分但不完全包含

 很明显看出改完后线段长度竟然变小了,那肯定不能选。

第三种情况两条线段包含关系

我们发现长度竟然没变

那么大体的思路就出来了选择两条相离的线段使这两条线段之间的距离最远即\left | r2 - l1 \right | 最大

AC代码如下

#include <bits/stdc++.h>
using namespace std;
const int N = 200005;
long long T , n , a[N] , b[N] , maxl , minr , ans;
void csh()
{
	memset(a , 0 , sizeof(a));
	memset(b , 0 , sizeof(b));
	maxl = ans = 0;
	minr = 1000000005;
}
int main()
{
	scanf("%lld" , &T);
	while(T--)
	{
		csh();//多组数据别忘了初始化
		scanf("%lld" , &n);
		for(int i = 1 ; i <= n ; i++) scanf("%lld" , &a[i]);
		for(int i = 1 ; i <= n ; i++) scanf("%lld" , &b[i]);
		for(int i = 1 ; i <= n ; i++)
		{
			ans += abs(a[i] - b[i]);
			if(a[i] > b[i]) swap(a[i] , b[i]);//为了编码方便咱们令a为左端点b为右端点
			maxl = max(maxl , a[i]);
			minr = min(minr , b[i]);
		}
		printf("%lld\n" , max(ans , ans + 2 * (maxl - minr)));
	}
	return 0;
} 

不知为什么这题在洛谷上开O2优化就超时,关了O2就AC,离谱!

(谁懂啊我月考物理AK了,哈哈哈哈哈哈) 

  • 7
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值