[APIO2010]特别行动队 --- 斜率优化DP

Posted ReMoon

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[APIO2010]特别行动队 --- 斜率优化DP相关的知识,希望对你有一定的参考价值。

[APIO2010]特别行动队

题面很直白,就不放了。

 

太套路了,做起来没点感觉了。

\(dp(i)=dp(j)+a*(s(i)-s(j))^{2}+b*(s(i)-s(j))+c\)

直接推出一个斜率优化的式子上单调队列就好了

 

时间/空间复杂度:\(O(n)\)

 

技术分享图片
#include<cstdio>
#define sid 1000500
#define ri register int
#define ll long long
#define dd double
using namespace std;

#define getchar() *S ++
char RR[30000005], *S = RR;
inline int read(){
    int p = 0, w = 1;
    char c = getchar();
    while(c > 9 || c < 0) {
        if(c == -) w = -1;
        c =  getchar();
    }
    while(c >= 0 && c <= 9) {
        p = p * 10 + c - 0;
        c = getchar();
    }
    return p * w;
}

ll dp[sid], sum[sid];
int q[sid], n, a, b, c;

#define x(g) (sum[(g)])
#define y(g) (dp[(g)] + a * sum[(g)] * sum[(g)] - b * sum[(g)])

inline dd s(int i,int j){
    return (dd)(y(i) - y(j)) / (dd)(x(i) - x(j));
}

int main(){
    fread(RR, 1, sizeof(RR), stdin);
    n = read(); a = read();
    b = read(); c = read();
    for(ri i = 1; i <= n; i ++) sum[i] = sum[i - 1] + read();
    ri fr = 1, to = 1;
    for(ri i = 1; i <= n; i ++){
        while(fr + 1 <= to && s(q[fr],q[fr + 1]) > 2 * a * sum[i]) fr ++;
        int p = q[fr];
        ll pp = sum[i] - sum[p];
        dp[i] = dp[p] + a * pp * pp + b * pp + c;
        while(fr + 1 <= to && s(q[to], q[to - 1]) <= s(i, q[to - 1])) to --;
        q[++ to]=i;
    }
    printf("%lld\n", dp[n]);
    return 0;
}
特别行动队

 

以上是关于[APIO2010]特别行动队 --- 斜率优化DP的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ 1911: [Apio2010]特别行动队 [斜率优化DP]

bzoj1911[Apio2010]特别行动队 斜率优化dp

APIO 2010 特别行动队 斜率优化DP

BZOJ1911 [Apio2010]特别行动队 - 动态规划 - 斜率优化

APIO 2010 特别行动队 | 斜率优化DP

[APIO2010]特别行动队