CF1740C Bricks and Bags 题解

21 篇文章 0 订阅
本文详细解析了 CF1740C 题目,指出其难度为 1400 的简单题。主要分析了如何对棍子进行排序,并通过四种条件简化问题,最终得出优化后的解决方案,强调不应过度复杂化问题。给出了基于 C++ 的解题思路和关键代码片段。
摘要由CSDN通过智能技术生成

众所周知,这道题的难度是 1400 1400 1400,所以是简单题。

2024/6/22UPD 不是这CSDN怎么自己给我调VIP文章了,不要太过分:(

分析

首先,坚信这是一道简单题,所以不要想复杂了。

首先我们需要对 a a a 数组排序,这点是肯定的,为啥应该不用我解释。

下面,我们假设 p 1 ,    p 2 ,    p 3 p_1, \;p_2,\; p_3 p1,p2,p3 分别为朋友在第 1 1 1 个,第 2 2 2 个和第 3 3 3 个背包中选择的棍子下标(注意,这里的下标都是指的排序后的数组下标)。我们可以发现,所有的分类情况下一定会满足下列四种条件之一:

{ p 1 < p 2 < p 3 p 1 > p 2 > p 3 min ⁡ ( p 1 ,    p 3 ) > p 2    (所有背包2里的东西都比1,3里的东西小) max ⁡ ( p 1 ,    p 3 ) < p 2    (所有背包2里的东西都比1,3里的东西大) \begin{cases} p_1 < p_2 < p_3 \\ p_1 > p_2 > p_3 \\ \min(p_1,\;p_3) > p_2 \;&\text{(所有背包2里的东西都比1,3里的东西小)}\\ \max(p_1,\;p_3) < p_2\;&\text{(所有背包2里的东西都比1,3里的东西大)} \end{cases} p1<p2<p3p1>p2>p3min(p1,p3)>p2max(p1,p3)<p2(所有背包2里的东西都比1,3里的东西小)(所有背包2里的东西都比1,3里的东西大)

翻译一下,这四种情况的答案分别是:

a n s = { ( a p 2 − a p 1 ) + ( a p 3 − a p 2 ) if     p 1 < p 2 < p 3 ( a p 3 − a p 2 ) + ( a p 2 − a p 1 ) if     p 1 > p 2 > p 3 ( a p 1 − a p 2 ) + ( a p 3 − a p 2 ) if     min ⁡ ( p 1 ,    p 3 ) > p 2    ( a p 2 − a p 3 ) + ( a p 2 − a p 1 ) if     max ⁡ ( p 1 ,    p 3 ) < p 2    ans=\begin{cases} (a_{p_2} - a_{p_1}) + (a_{p_3} - a_{p_2}) &\text{if \;} p_1 < p_2 < p_3 \\ (a_{p_3} - a_{p_2}) + (a_{p_2} - a_{p_1}) &\text{if \;} p_1 > p_2 > p_3 \\ (a_{p_1} - a_{p_2}) + (a_{p_3} - a_{p_2}) &\text{if \;} \min(p_1,\;p_3) > p_2 \;\\ (a_{p_2} - a_{p_3}) + (a_{p_2} - a_{p_1}) &\text{if \;} \max(p_1,\;p_3) < p_2\; \end{cases} ans= (ap2ap1)+(ap3ap2)(ap3ap2)+(ap2ap1)(ap1ap2)+(ap3ap2)(ap2ap3)+(ap2ap1)if p1<p2<p3if p1>p2>p3if min(p1,p3)>p2if max(p1,p3)<p2

你感性理解一下,你就会发现前两种情况一定不会比后两种优(因为如果出现这两种情况,你只需要将其中两个背包交换一下位置就会转化为后面两种,而明显转化后会更优,这个你自己手模一下应该很显然),于是我们就只用考虑后面两种情况就可以了,即:

a n s = { ( a p 1 − a p 2 ) + ( a p 3 − a p 2 ) if     min ⁡ ( p 1 ,    p 3 ) > p 2    ( a p 2 − a p 3 ) + ( a p 2 − a p 1 ) if     max ⁡ ( p 1 ,    p 3 ) < p 2    ans=\begin{cases} (a_{p_1} - a_{p_2}) + (a_{p_3} - a_{p_2}) &\text{if \;} \min(p_1,\;p_3) > p_2 \;\\ (a_{p_2} - a_{p_3}) + (a_{p_2} - a_{p_1}) &\text{if \;} \max(p_1,\;p_3) < p_2\; \end{cases} ans={(ap1ap2)+(ap3ap2)(ap2ap3)+(ap2ap1)if min(p1,p3)>p2if max(p1,p3)<p2

但是你会发现,即使是这样,我们任然不能很好的限制计算方法,于是我们考虑继续加强条件。

下面我们以第三种情况为例加强限制(第四种的推理过程是一样的):

我们假设有 min ⁡ ( p 1 ,    p 3 ) > p 2 + 1 \min(p_1,\;p_3) > p_2 + 1 min(p1,p3)>p2+1 (注意这里的都是下标之间的关系),我们分下列三种情况分析(注意,我们下面的讨论都基于我们假设朋友一定会选 p 1 ,    p 2 ,    p 3 p_1,\;p_2,\;p_3 p1,p2,p3 的基础上):

  1. 如果 p 2 + 1 p_2 + 1 p2+1 这根棍子被放在了第 1 1 1 个背包中,那么朋友在背包 1 1 1 中选择下标为 p 2 + 1 p_2 + 1 p2+1 的棍子而不是 p 1 p_1 p1,因为 a p 2 + 1 − a p 2 ⩽ a p 1 − a p 2 a_{p_2 + 1} - a_{p_2} \leqslant a_{p_1} - a_{p_2} ap2+1ap2ap1ap2,因此假设不成立;
  2. 如果 p 2 + 1 p_2 + 1 p2+1 这根棍子被放在了第 2 2 2 个背包中,那么朋友在背包 2 2 2 中选择下标为 p 2 + 1 p_2 + 1 p2+1 的棍子而不是 p 2 p_2 p2,因为 ( a p 1 − a p 2 + 1 ) + ( a p 3 − a p 2 + 1 ) ⩽ ( a p 1 − a p 2 ) + ( a p 3 − a p 2 ) (a_{p_1} - a_{p_2 + 1}) + (a_{p_3} - a_{p_2 + 1}) \leqslant (a_{p_1} - a_{p_2}) + (a_{p_3} - a_{p_2}) (ap1ap2+1)+(ap3ap2+1)(ap1ap2)+(ap3ap2),因此假设不成立;
  3. 如果 p 2 + 1 p_2 + 1 p2+1 这根棍子被放在了第 3 3 3 个背包中,那么朋友在背包 3 3 3 中选择下标为 p 2 + 1 p_2 + 1 p2+1 的棍子而不是 p 3 p_3 p3,因为 a p 2 + 1 − a p 2 ⩽ a p 3 − a p 2 a_{p_2 + 1} - a_{p_2} \leqslant a_{p_3} - a_{p_2} ap2+1ap2ap3ap2,因此假设不成立。

于是我们发现,在 min ⁡ ( p 1 ,    p 3 ) > p 2 + 1 \min(p_1,\;p_3) > p_2 + 1 min(p1,p3)>p2+1 时,朋友一定不会选择我们给他“指定”的那三个棍子,于是我们把条件收束为:

{ min ⁡ ( p 1 ,    p 3 ) > p 2    &    min ⁡ ( p 1 ,    p 3 ) = p 2 + 1 max ⁡ ( p 1 ,    p 3 ) < p 2    &    max ⁡ ( p 1 ,    p 3 ) = p 2 − 1 \begin{cases} \min(p_1,\;p_3) > p_2 \; \& \; \min(p_1,\;p_3) = p_2 + 1 \\ \max(p_1,\;p_3) < p_2\; \& \; \max(p_1,\;p_3) = p_2 - 1 \end{cases} {min(p1,p3)>p2&min(p1,p3)=p2+1max(p1,p3)<p2&max(p1,p3)=p21

的时候我们才能确定朋友所选取的棍子就是我们“指定”的那三根。

这个条件化简一下其实就是:

{ min ⁡ ( p 1 ,    p 3 ) = p 2 + 1 max ⁡ ( p 1 ,    p 3 ) = p 2 − 1 \begin{cases} \min(p_1,\;p_3) = p_2 + 1 \\ \max(p_1,\;p_3) = p_2 - 1 \end{cases} {min(p1,p3)=p2+1max(p1,p3)=p21

而我们需要最大化 ∣ a p 2 − a p 1 ∣ + ∣ a p 3 − a p 2 ∣ |a_{p_2}-a_{p_1}|+|a_{p_3} - a_{p_2}| ap2ap1+ap3ap2,于是我们很显然将 min ⁡ ( p 1 ,    p 3 ) \min(p_1,\;p_3) min(p1,p3) 定为 1 1 1 或者让 max ⁡ ( p 1 ,    p 3 ) \max(p_1,\;p_3) max(p1,p3) n n n,这样我们得到的解一定最优(注意此时我们是在计算答案,这里的 min 和 max 与上式中并不表同一含义,具体看下面的式子)。但是此时我们也只是确定了其中一边的取值,那么另一边枚举就行了,于是我们有以下计算式:

a n s = m a x { m a x i = 3 n    { ( a i − a 1 ) + ( a i − a i − 1 ) } 此时的排列是  1 ,    i ∼ n ,    2 ∼ i − 1 m a x i = 1 n − 2    { ( a n − a i ) + ( a i + 1 − a i ) } 此时的排列是  n ,    1 ∼ i ,    i + 1 ∼ n − 1 ans=max\begin{cases} max_{i = 3}^{n}\; \{(a_i - a_1) + (a_i - a_{i - 1})\} &\text{此时的排列是 } 1,\; i \sim n, \; 2 \sim i - 1 \\ max_{i = 1}^{n - 2} \; \{(a_n - a_i) + (a_{i + 1} - a_i)\} &\text{此时的排列是 } n,\; 1 \sim i, \; i + 1 \sim n - 1 \end{cases} ans=max{maxi=3n{(aia1)+(aiai1)}maxi=1n2{(anai)+(ai+1ai)}此时的排列是 1,in,2i1此时的排列是 n,1i,i+1n1

于是我们就做完了,对就是这么简单,区区 1400 1400 1400 而已,是真的不能把他想的太难了,不然真的很容易想偏。

代码

//省略快读和头文件
int T;
int a[MAXN];

int main()
{
//	freopen(".in", "r", stdin);
//	freopen(".out", "w", stdout);

	T = inpt();
	while(T--) {
		int n = inpt();
		for(int i = 1; i <= n; ++i)
			a[i] = inpt();
		sort(a + 1, a + n + 1);
		
		int ans = 0;
		for(int i = 3; i <= n; ++i)
			ans = max(ans, a[i] - a[1] + a[i] - a[i - 1]);// 1, i ~ n, 2 ~ i - 1
		for(int i = 1; i <= n - 2; ++i)
			ans = max(ans, a[n] - a[i] + a[i + 1] - a[i]);// n, 1 ~ i, i + 1 ~ n - 1
		
		printf("%d\n", ans);
	}

	fclose(stdin);
	fclose(stdout);
	return 0;
}
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值