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
", sum);
    return 0;
}
View Code
要么优秀要么生锈
原文地址:https://www.cnblogs.com/Superwalker/p/7851436.html