USACO08MAR Land Acquisition

题目地址

题解

斜率优化。

  1. 合并部分土地,使$y$递减,$x$递增
  2. 注意单调队列的增减性。
  3. 决策的单调性…
  4. 凸壳的中间点在什么情况下一定不优?
    考虑不同的限定条件,可以证明两端分别在2种情况下都更优。
    这是单调队列单调的理由。
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    #include <cstdio>
    #include <cstdlib>
    #include <algorithm>
    #include <cstring>
    #include <cctype>
    #define INF 2000000000
    using namespace std;
    typedef long long ll;
    typedef pair<ll,ll> P;
    P a[50005],b[50005];
    int n,cnt=0,que[50005]={0},l=1,r=1;
    ll f[50005];
    double slope(int j,int k){
    return (f[k]-f[j])/(b[j+1].second-b[k+1].second);
    }
    int read(){
    int f=1,x=0;char c=getchar();
    while(c<'0'||c>'9'){if(c=='-')f=-f;c=getchar();}
    while(c>='0'&&c<='9')x=x*10+c-'0',c=getchar();
    return f*x;
    }
    void init(){
    n=read();
    for(int i=1;i<=n;i++)
    a[i].first=read(),a[i].second=read();
    sort(a+1,a+n+1);
    for(int i=1;i<=n;i++){
    //printf("%d %d\n",a[i].first,a[i].second);
    while(cnt&&a[i].second>=b[cnt].second)
    cnt--;
    b[++cnt]=a[i];
    }
    }
    void solve(){
    que[r++]=0;
    for(int i=1;i<=cnt;i++){
    while(r-l>1&&slope(que[l],que[l+1])<b[i].first)
    l++;
    f[i]=f[que[l]]+b[que[l]+1].second*b[i].first;
    while(r-l>1&&slope(que[r-2],que[r-1])>slope(que[r-1],i))
    r--;
    que[r++]=i;
    }
    printf("%lld\n",f[cnt]);
    }
    int main(){
    init();
    solve();
    return 0;
    }