jzoj 6305. 最小值

Description

详见OJ

Solution

第一眼看上去好像斜率\(DP\),但仔细一看发现不能用单调队列维护。
然后\(GG\)
正解使用单调栈来维护。
我们发现,我们维护的单调栈\(g[]\)\(a[]\)是呈单调不下降的。
对于新加入的点i,我们需要将单调栈中\(a[]\)大于\(a[i]\)的弹出栈中,
因为这些点的答案需要重新计算。
对于弹出的\(f[g[]]\)我们与\(f[i-1]\)\(max\),然后更新答案,并将点\(i\)加入栈中。

Code

#include <cstdio>
#define N 200010
#define ll long long
#define mem(x, a) memset(x, a, sizeof x)
#define fo(x, a, b) for (int x = a; x <= b; x++)
#define fd(x, a, b) for (int x = a; x >= b; x--)
using namespace std;
const int inf = 2147483647;
int n, a[N], g[N], len = 0;
ll A, B, C, D, f[N], ma[N], t;

inline int read()
{
    int x = 0, f = 0; char c = getchar();
    while (c < '0' || c > '9') f = (c == '-') ? 1 : f, c = getchar();
    while (c >= '0' && c <= '9') x = (x << 1) + (x << 3) + (c ^ 48), c = getchar();
    return f ? -x : x;
}

ll solve(int x) {return A * x * x * x + B * x * x + C * x + D;}

ll max(ll x, ll y) {return x > y ? x : y;}

int main()
{
    freopen("min.in", "r", stdin);
    freopen("min.out", "w", stdout);
    n = read(), A = read(), B = read(), C = read(), D = read();
    fo(i, 1, n) a[i] = read();
    fo(i, 1, n)
    {
        t = f[i - 1];
        while (len && a[g[len]] >= a[i]) t = ma[len] > t ? ma[len] : t, len--;
        g[++len] = i, ma[len] = t;
        f[i] = t + solve(a[i]);
        if (len > 1 && f[g[len - 1]] > f[i]) f[i] = f[g[len - 1]];
    }
    printf("%lld\n", f[n]);
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值