POJ3045
题意
给n只奶牛,每只奶牛都有两个属性, 风险值(s[i])和抗压值(w[i]),现在要把这些牛垒在一起, 每个牛都有一个危险值位他上面的牛的风险值之和减去它的抗压值,问最大危险值得最小值(n<=5e4,1 <= w[i]<= 1e4,1 <= s[i] <= 1,000,000,000 )
分析
二分? 怎么check(mid)?? 想不到
正解:贪心 ,按照每头牛s[i] +w[i]之和排序,大的放下面(感性的想一下,似乎何有道理???)
证明:现在考虑中间的任意两只 i 和 i+1只牛, 假设现在是最佳排列方式,现改变i和i+1头牛的顺序,由于前面和后面都不受影响,所以可以单独考虑
现默认从上到下为第1~n头牛,设前i-1头牛的总风险值为W
未改变:
第i个位置:W-w[i]
第i+1位置: W+s[i] - w[i+1] -----1
改变后:
第i个位置: W-w[i+1]
第i+1位置: W+s[i+1]-w[i] ------2
方程1 < 方程2 可以推出 s[i] + w[i] < s[i+1] + w[i+1]
#include <cstdio> #include <iostream> #include <queue> #include <algorithm> #include <cstring> #include <set> using namespace std; #define ll long long const int maxn = 1e5 + 10; struct node { int w, s; friend bool operator < (node a, node b) { return a.w+a.s < b.w+b.s; } }a[maxn]; int n; int main() { scanf("%d", &n); for(int i = 1; i <= n; i++) { scanf("%d%d", &a[i].w, &a[i].s); } sort(a+1,a+n+1); ll sum = -1ll*a[1].s; ll ans=1ll*a[1].w; for(int i = 2; i <= n; i++) { sum=max(sum, 1ll*(ans-a[i].s)); ans+=1ll*a[i].w; } printf("%lld\n", sum); return 0; }
要么优秀要么生锈