安徽省网站建设_网站建设公司_阿里云_seo优化
2025/12/17 21:32:18 网站建设 项目流程

邻项交换贪心小记

主要参考来源 [OI-wiki 贪心](贪心 - OI Wiki)。wiki原话:用排序法常见的情况是输入一个包含几个(一般一到两个)权值的数组,通过排序然后遍历模拟计算的方法求出最优值。

直接看题目吧,然后证明啥的也不严谨,主要是方便自己回顾的。

LG1080 [NOIP 2012 提高组] 国王游戏

恰逢 H 国国庆,国王邀请 \(n\) 位大臣来玩一个有奖游戏。首先,他让每个大臣在左、右手上面分别写下一个整数,国王自己也在左、右手上各写一个整数。然后,让这 \(n\) 位大臣排成一排,国王站在队伍的最前面。排好队后,所有的大臣都会获得国王奖赏的若干金币,每位大臣获得的金币数分别是:排在该大臣前面的所有人的左手上的数的乘积除以他自己右手上的数,然后向下取整得到的结果。

重新安排队伍顺序,最小化奖赏最多的大臣的奖赏。

左右手上的数分别记为 \(a_i,b_i\),现在考虑相邻的两个大臣 \(x,y\),他们之间的排列是否最优。假设两人前面大臣所有 \(a_i\) 的乘积为 \(s\)

目前排列方式,两人奖赏的较大值为 \(\max\{\frac{s}{b_x},\frac{s\cdot a_{x}}{b_y} \}\)

同理,若两人位置交换,奖赏较大值为 \(\max\{\frac{s}{b_y},\frac{s\cdot a_y}{b_x} \}\)

如果当前排列更优,则有:

\[\max\{\frac{s}{b_x},\frac{s\cdot a_{x}}{b_y} \}<\max\{\frac{s}{b_y},\frac{s\cdot a_y}{b_x} \} \]

提出 \(s\) 再通分,得到最终形式

\[\max(b_y,a_x\cdot b_x)<\max(b_x,a_y\cdot b_y) \]

则最后的序列需要满足这个条件,写入 std::sort 中的 cmp 函数即可。

然后这题要高精度所以我这次就没重写了,如果有一些细节的话我也不知道。

LG2123 皇后游戏

饺子醋来了,闲话后面再说。

形式化地讲,设第 \(i\) 位大臣有一个二元组 \((a_i,b_i)\),第 \(i\) 位大臣获得的奖金数目 \(c_i\) 可以表示为(定义 \(c_0=0\)):

\[c_i=\max\{c_{i-1},\sum_{j=1}^{i}a_j \}+b_i \]

现在请对每位大臣排序,最小化最大的 \(c_i\)

为了方便,还是定义一个前缀和 \(s_i=\sum_{j=1}^{i} a_j\)。变成 \(c_i=\max(c_{i-1},s_i)+b_i\)

显然 \(c_i\) 是递增的,于是只需要最小化 \(c_n=\max(c_{n-1},s_n)+b_n\)

\(b_n\) 写在里面,再把 \(c_{n-1}\) 拆开,可以变成

\[c_n=\max\{s_{n}+b_n,\max(c_{n-2},s_{n-1})+b_{n-1}+b_{n}\} \]

继续把 \(c_{n-2}\) 拆开,可以变成

\[c_n=\max\{s_n+b_n,s_{n-1}+b_{n-1}+b_n,\max(c_{n-3},s_{n-2})+b_{n-2}+b_{n-1}+b_{n} \} \]

然后一直拆 \(c\),直到拆到 \(c_1\),可以得出 \(c_n\) 可以写作 \(n\) 个式子的最大值,如下

\[\begin{align} c_n&=\max_{i=1}^{n}(s_i+\sum_{j=i}^{n}b_j)\\ &=\max_{i=1}^{n}(\sum_{i=1}^{j}a_j+\sum_{j=i}^{n}b_j) \end{align} \]

然后就可以邻项交换贪心了,思考一下交换某相邻两项是否会让答案更优。交换第 \(x\) 和第 \((x+1)\) 项,只会影响 \((\sum_{j=1}^{x}a_j+\sum_{j=x}^{n}b_j)\)\((\sum_{j=1}^{x+1}a_j+\sum_{j=x+1}^{n}b_j)\) 两项的值。令 \(\sum_{j=1}^{x-1}a_j=pre,\sum_{j=x+2}^{n}b_j=suf\)。则如果目前排列更优,则有

\[\max(pre+a_x+b_x+b_{x+1}+suf,pre+a_x+a_{x+1}+b_{x+1}+suf)<\max(pre+a_{x+1}+b_{x+1}+b_{x}+suf,pre+a_{x+1}+a_{x}+b_x +suf) \]

\[\max(a_x+b_x+b_{x+1},a_x+a_{x+1}+b_{x+1})<\max(a_{x+1}+b_{x+1}+b_{x},a_{x+1}+a_{x}+b_{x}) \]

\[\max(-a_{x+1},-b_x)<\max(-a_x,-b_{x+1}) \]

\[\min(a_{x+1},b_x)>\min(a_x,b_{x+1}) \]

好的基本思考就这些,写入 std::sortcmp 排序。

但是由于有的时候会有相邻几项 \(\min(a_y,b_x)\)\(\min(a_x,b_y)\) 相同,导致远在天边的两项虽然应该交换顺序但是没有交换,所以排序的时候若相等,再考虑对第二第三关键字再排序,底层逻辑就没深究了,具体见代码吧。

const int N=200005;
struct node{ll a,b;
}a[N];
inline bool cmp(node x,node y){if(min(x.b,y.a)==min(y.b,x.a))return y.a==x.a?x.b>y.b:y.a>x.a;return min(x.b,y.a)>min(y.b,x.a);
}
int n;
int main(){int T;scanf("%d",&T);while(T--){scanf("%d",&n);for(int i=1;i<=n;++i)scanf("%lld%lld",&a[i].a,&a[i].b);sort(a+1,a+1+n,cmp);ll s=0,c=0;for(int i=1;i<=n;++i){s+=a[i].a;c=max(s,c)+a[i].b;}printf("%lld\n",c);}return 0;
}

后记

这题目居然是紫题没绷住,那看来 NOIP2025 T2 的紫也没那么难?不过这个 cmp 的细节确实有点东西,以后要注意,如果是 ICPC 赛制估计要罚时多发红温了。以及多倍经验,感觉 n 年后再来看降绿了。

嗯最后大美雨课堂又忘记做了,以及这个是大美课上写的虽然提一嘴无意义。

需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询