相邻两项比较的方法深入人心(
感谢那个第一位写出此题正解且没有被 hack 掉的大佬。
建议这一道题目和国王游戏一起看
但是这两道题目在算法上却有一些本质的不同。(这一篇会主要讲讲)
整理做法
首先看到安排顺序,考虑进行相邻两项的比较,跟国王游戏的套路没啥区别;
再来看一眼题目中给出的表达式:
这其实就足以证明越往后钱就约多,然而皇后却希望奖金最多的大臣得到的钱要尽量少,所以我们要让后面的大臣的奖金尽量少;
相邻两项之间的比较
国王游戏这一道题目我们是比较的
说简单点也就是比较交换前的 和交换后的 但是这里我们显然是不用这么去比较的,其他题解都讲的很清楚力,由于 相对于其他的量来说是一只在变化的,所以,我们只需要比较 交换前的 和交换后的 就可以了;
然后其实这一部分比较就是一个一直化简、举例的过程,别的题解讲的很透了,这里不说了,总之我们珂以推出下面的柿子:
(注:这里满足的条件是 )
从这里我们可以得出要来:
若 那么调换一下 和 的位置就可;
这个不受这两个大臣前后的大臣的影响。
但是为了证实这个是正确的,我们就需要考虑一个极端的可能性:
由于上面那个柿子和 与 的大小有着直接的关系,我们不妨分情况来看一下:
-
若 ,因此, 并且 不难看出,这一组要按照 的升序 排列;
-
若 ,则有 或者 这一组要按照 的降序 排列;
所以我们可以得出一个结论:
把 的部分尽量放在前面,然后按照 的升序排列,后面的部分显然就是 的部分,按照 的降序排列
于是,可以得出代码:
#include <iostream>
#include <algorithm>
#define ll long long
using namespace std;
struct Node {
ll a, b, t;
bool operator<(const Node& n2)const {
if (t != n2.t)
{
return t < n2.t;
}
if (t != 3) {
return a < n2.a;
}
else
{
return b > n2.b;
}
}
}node[100005];
//这里可以对比国王游戏的代码部分
int main() {
int T, n;
cin >> T;
while (T--)
{
cin >> n;
for (int i = 1; i <= n; i++) {
cin >> node[i].a >> node[i].b;
if (node[i].a < node[i].b) {
//a[i]<b[i]的情况:
node[i].t = 1;
}
else if (node[i].a == node[i].b) {
//a[i]=b[i]的情况:
node[i].t = 2;
}
else {
node[i].t = 3;
}
}
sort(node + 1, node + 1 + n);
ll x, y;
x = node[1].a, y = node[1].a + node[1].b;//开始第一个人的钱数
for (int i = 2; i <= n; i++) {
x += node[i].a;
y = max(y, x) + node[i].b;
}
cout << y << endl;
}
return 0;
}
代码没啥好说的吧;
总结一下,这道题最难的地方是推柿子还有最后的证明过程,希望相邻两项比较的方法可以深入人心吧。
本文作者:zsdqwq
本文链接:https://www.cnblogs.com/wo-de-bo-ke-wo-zuo-zhu/p/solution-p2123.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步