设每只奶牛重量为 $w$ ,能力为 $s$ ,假设叠罗汉如下($w_1,s_1$ 在最上面):
$$
w_1,s_1 \\
w_2,s_2 \\
… \\
w_i,s_i \\
w_{i+1},s_{i+1} \\
… \\
w_n,s_n
$$
现在交换第 $i$ 头奶牛和第 $i+1$ 头奶牛的顺序,交换前后这两头奶牛的风险值如下表所示:
交换前 | 交换后 | |
---|---|---|
第 $i$ 头牛 | $w_1+…+w_{i-1}-s_i$ | $w_1+…+w_{i-1}+w_{i+1}-s_i$ |
第 $i+1$ 头牛 | $w_1+…+w_i-s_{i+1}$ | $w_1+…+w_{i-1}-s_{i+1}$ |
只比较大小的话,上述表格中两头奶牛的风险值可以简化为:
交换前 | 交换后 | |
---|---|---|
第 $i$ 头牛 | $-s_i$ | $w_{i+1}-s_i$ |
第 $i+1$ 头牛 | $w_i-s_{i+1}$ | $-s_{i+1}$ |
所以比较 $w_i-s_{i+1}$ 和 $w_{i+1}-s_i$ 两个值的大小关系:
若 $w_i-s_{i+1}>w_{i+1}-s_i$ ,则表示交换前风险最大值更大,所以需要交换。移项得:
$w_i+s_i>w_{i+1}+s_{i+1}$
整理得:
$$
w_i+s_i>w_{i+1}+s_{i+1} \quad 交换前风险最大值更大,所以需要交换 \\
w_i+s_i<w_{i+1}+s_{i+1} \quad 交换后风险最大值更大,所以不需要交换
$$
每次必要的交换后,局部的风险最大值都会更小,也就是更优。
所以要按照每头奶牛的 $w+s$ 从小到大排序。从罗汉顶向下方依次遍历,寻找风险值的最大值
#include<bits/stdc++.h>
using namespace std;
typedef pair<int, int> PII;
const int N = 50010;
int n;
PII cow[N];
int main()
{
cin >> n;
for (int i = 0; i < n; i ++)
{
int w, s;
cin >> w >> s;
cow[i] = {w + s, w};
}
sort(cow, cow + n); // 默认按照 cow[i].first 从小到大排序
int res = -2e9, sum = 0;
for (int i = 0; i < n; i ++) // 自罗汉顶向下遍历
{
int s = cow[i].first - cow[i].second; // 得到每头奶牛的 s ,即能力值
int w = cow[i].second;
res = max(res, sum - s); // res 为最大风险,sum 为头顶所有奶牛的重量,s 为能力值
sum += w;
}
cout << res << endl;
return 0;
}