P3195 [HNOI2008] Toys containers (slope optimization DP)

Title link
set \ (d [i] \) of the front of \ (I \) required to give a toy boxed minimum cost
readily available dynamic transfer equation:
\ [D [I] = min (D [J] + (s [i] -s [j
] + ij-1-L) ^ 2), (j <i) \] where \ (S [I] = \ ^ sum_1 [I] \) iC , the complexity of ordinary DP is \ (O (^ n-2) \) . After optimization of the slope will become \ (O (n-) \) .
Careful observation we can make ease of representation \ (f [i] = s
[i] + i \) then the equation becomes

\ [D [i] = min (d [j] + (f [i] -f [j] -1-L) ^ 2) \]

We discuss \ (j_1, j_2 (1 \ le j_1 <j_2 <i) \) decision, assuming that \ (j_2 \) than \ (j_1 \) better, then there

\(d[j_1] + (f[i] -f[j_1]-1-L)^2 \ge d[j_2]+(f[i]-f[j_2]-1-L)^2\)

Expanded get

\(d[j_1] + f[i]^2 - 2\times f[i]\times (f[j_1]+1+L)+(f[j_1]+1+L)^2 \ge d[j_2]+f[i]^2-2\times f[i]\times (f[j_2]+1+L)+(f[j_2]+1+L)^2\)

After transposition available

\(2\cdot f[i]\ge {d[j_2]+(f[j_2]+1+L)^2-d[j_1]-(f[j_1]+1+L)^2 \over f[j_2]-f[j_1]}\)

Order \ (G [I] = F [I]. 1 + L + \) , there

\(2\cdot f[i]\ge {(d[j_2]+g[j_2])-(d[j_1]+g[j_1])\over f[j_2]-f[j_1]}\)

Therefore, by maintaining a queue decision set, when the \ (j_1 <j_2 \) , the above equation is satisfied and, \ (j_1 \) dequeued.
Also, because \ (f [i] \) with \ (I \) monotonically. So calculate \ (d [i] \) then you want to \ (i \) when the team can not be ruled out in time element for decision-making.
How to calculate? The slope of the tail should monotone, holding with \ (f [i] \) is consistent with the monotonicity can.

#include <bits/stdc++.h>
using namespace std;
const int N = 50010;
typedef long long ll;
typedef long double db;
db c[N],d[N],f[N],s[N],g[N];
int n,L;
int q[N],l,r;
db sqr(db x){return x * x;}
db slope(int i,int j){
    return ((d[i] +  g[i]) - (d[j] + g[j])) / (f[i] - f[j]);
}
int main(){
    scanf("%d%d",&n,&L);
    l=r=1;
    for(int i=1;i<=n;i++){
        cin>>c[i];
        s[i]=s[i-1] + c[i];
        f[i] = s[i] + i;
        g[i] = (f[i] + 1 + L) * (f[i] + 1 + L);
    }
    g[0] = (ll)(1+L)*(1+L);//注意0号元素的g值初始化
    for(int i=1;i<=n;i++){
        while(l < r && slope(q[l],q[l+1]) < 2 * f[i])l++;
        int j = q[l];
        d[i] = d[j] + sqr(f[i]-f[j]-1-L);
        while(l < r && slope(q[r],q[r-1]) > slope(i,q[r-1]))r--;//满足队尾斜率单调性
        q[++r] = i;//入队
    }
    printf("%lld\n",(ll)d[n]);
    return 0;
}

Guess you like

Origin www.cnblogs.com/1625--H/p/11266927.html