设每只奶牛重量为 w ,能力为 s ,假设叠罗汉如下(w1,s1 在最上面):
w1,s1w2,s2…wi,siwi+1,si+1…wn,sn
现在交换第 i 头奶牛和第 i+1 头奶牛的顺序,交换前后这两头奶牛的风险值如下表所示:
交换前 | 交换后 | |
---|---|---|
第 i 头牛 | w1+…+wi−1−si | w1+…+wi−1+wi+1−si |
第 i+1 头牛 | w1+…+wi−si+1 | w1+…+wi−1−si+1 |
只比较大小的话,上述表格中两头奶牛的风险值可以简化为:
交换前 | 交换后 | |
---|---|---|
第 i 头牛 | −si | wi+1−si |
第 i+1 头牛 | wi−si+1 | −si+1 |
所以比较 wi−si+1 和 wi+1−si 两个值的大小关系:
若 wi−si+1>wi+1−si ,则表示交换前风险最大值更大,所以需要交换。移项得:
wi+si>wi+1+si+1
整理得:
wi+si>wi+1+si+1交换前风险最大值更大,所以需要交换wi+si<wi+1+si+1交换后风险最大值更大,所以不需要交换
每次必要的交换后,局部的风险最大值都会更小,也就是更优。
所以要按照每头奶牛的 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;
}