[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