JZOJ 5347. 【NOIP2017提高A组模拟9.5】遥远的金字塔

Description

这里写图片描述

分析

其实这就是很明显的一道斜率优化的dp式子,我们首先可以得到最显然的dp方程,设f[i][j]表示前i层数分成j个不相交的矩形的最大面积,那么我们有:

f[i][j]=max(f[i-k+1][j-1]+(y[i]-x[i])*k),k为与当前这一块联通的矩形宽。

很明显,这个式子等价于f[i][k]=max(f[j][k-1]+(y[i]-x[i])*(i-j)),然后就可以斜率优化了

有一个小细节,我就是这里错了然后就很愉快爆炸了,最终的答案显然不应该是f[n][k],而应该是f[k+1][k]到f[n][k]的最大值

代码

#include <bits/stdc++.h>

#define K 105
#define N 20050
#define ll long long

int read()
{
    int x = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9') {if (ch == '-') f = -1; ch = getchar();}
    while (ch >= '0' && ch <= '9') {x = x * 10 + ch - '0'; ch = getchar();}
    return x * f;
}

struct NOTE
{
    ll x,y;
}a[N];

ll Q[N];
int head,tail;

ll sum[N];

ll f[N][K];

int main()
{
    freopen("pyramid.in","r",stdin);
    freopen("pyramid.out","w",stdout);
    int n = read(), k = read();
    for (int i = 1; i <= n; i++)
        a[i].x = read(), a[i].y = read(), sum[i] = a[i].y - a[i].x + 1;
    for (int j = 1; j <= k; j++)
    {
        head = 1, tail = 1;
        Q[head] = 0;
        for (int i = 1; i <= n; i++)
        {
            while (head < tail && sum[i] * (Q[head] - Q[head + 1]) >= f[Q[head]][j - 1] - f[Q[head + 1]][j - 1])
                head++;
            f[i][j] = f[Q[head]][j - 1] + sum[i] * i - sum[i] * Q[head];
            while (head < tail && (f[Q[tail - 1]][j - 1] - f[Q[tail]][j - 1]) * (Q[tail] - i) <= (f[Q[tail]][j - 1] - f[i][j - 1]) * (Q[tail - 1] - Q[tail]))
                tail--;
            Q[++tail] = i;
        }
    }
    ll ans = 0;
    for (int i = k + 1; i <= n; i++)
        ans = std::max(f[i][k], ans);
    printf("%lld\n",ans);
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值