HNOI 2008 玩具装箱toy

HNOI 2008 玩具装箱toy

    这是我做的第二个斜率优化+单调队列的dp了,做完这个题的感觉就是,如果一个dp可以用斜率优化的话,那么由动态转移方程就必须能推得下面的不等式:

    设j<k且在更新i时k比j优,那么可以得到不等式f(i)>g(j,k),其中f(i)是关于i的单调递增函数。

#include<stdio.h>
#include<string.h>
#define MAXD 50010
int a[MAXD], q[MAXD], N, L;
long long int f[MAXD], A[MAXD];
void init()
{
int i, j, k;
A[0] = 0;
for(i = 1; i <= N; i ++)
{
scanf("%d", &a[i]);
A[i] = A[i - 1] + a[i];
}
}
long long int sqr(long long int x)
{
return x * x;
}
long long int gett(int i)
{
return i + A[i];
}
long long int getf(int i)
{
return f[i] + sqr(gett(i)) + 2 * (1 + L) * gett(i);
}
void solve()
{
int i, j, k, front, rear, x, y, z;
front = rear = 0;
q[rear ++] = 0;
f[0] = 0;
for(i = 1; i <= N; i ++)
{
while(front < rear - 1)
{
x = q[front], y = q[front + 1];
if(2 * gett(i) * (gett(y) - gett(x)) < getf(y) - getf(x))
break;
++ front;
}
j = q[front];
f[i] = f[j] + sqr(A[i] - A[j] + i - j - 1 - L);
q[rear] = i;
for(j = rear - 1; j > front; j --)
{
x = q[j - 1], y = q[j], z = q[j + 1];
if((getf(y) - getf(x)) * (gett(z) - gett(y)) < (getf(z) - getf(y)) * (gett(y) - gett(x)))
break;
q[rear = j] = q[j + 1];
}
++ rear;
}
printf("%lld\n", f[N]);
}
int main()
{
while(scanf("%d%d", &N, &L) == 2)
{
init();
solve();
}
return 0;
}


原文地址:https://www.cnblogs.com/staginner/p/2390775.html