[SDOI2016]征途

Posted cold-cold

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了[SDOI2016]征途相关的知识,希望对你有一定的参考价值。

技术分享图片

 

这道题特别坑

状态转移是 f[i][k+1]=f[j][k]+(sum[i]-sum[j])*(sum[i]-sum[j]);

转换后变为 f[j][k]+sum[j]*sum[j]=f[i][k+1]+2*sum[i]*sum[j];

但是我在这里要说的是一个初值的问题

通常情况下斜率优化的题目都是不需要赋初值的

但因为f[i][1]全都为0,所以导致后续dp值全部出错

所以我们应将f[i][2]赋上初值为sum[i]*sum[i]

 总体实现如下:

#include <algorithm>
#include <iostream>
#include <cmath>
#include <cstring>
#include <map>
#include <string>
#include <vector>
#include <queue>
#include <stack>
#include <cstdio>
#include <cstdlib>
using namespace std;
typedef long long ll;
inline ll read()
{
    register ll p(1),a(0);register char ch=getchar();
    while((ch<0||ch>9)&&ch!=-) ch=getchar();
    if(ch==-) p=-1,ch=getchar();
    while(ch>=0&&ch<=9) a=a*10+ch-48,ch=getchar();
    return a*p;
}
//f[i][k+1]=f[j][k]+(sum[i]-sum[j])*(sum[i]-sum[j]);
//f[j][k]+sum[j]*sum[j]=f[i][k+1]+2*sum[i]*sum[j];
const ll N=3010;
ll n,kk,f[N][N],sum[N],Q[N],head=0,tail=0;
inline double getx(int x){return sum[x];}
inline double gety(int x,int now){return f[x][now]+sum[x]*sum[x];}
inline double che(int x,int y,int now){return (gety(y,now)-gety(x,now))/(getx(y)-getx(x));}
int main()
{
//    freopen("input","r",stdin);
//    freopen("output","w",stdout);
    n=read(),kk=read();
    for(register int i=1;i<=n;i++) sum[i]=sum[i-1]+read(),f[i][2]=sum[i]*sum[i];
    
    for(register int k=2;k<=kk;k++,head=tail=0)
        for(register int i=1,j;i<=n;i++)
            {
                while(head<tail&&che(Q[head],Q[head+1],k)<2*sum[i]) ++head;
                j=Q[head];f[i][k+1]=f[j][k]+(sum[i]-sum[j])*(sum[i]-sum[j]);
                while(head<tail&&che(Q[tail-1],Q[tail],k)>che(Q[tail],i,k)) --tail;
                Q[++tail]=i;
            }
    printf("%lld
",f[n][kk+1]*kk-sum[n]*sum[n]);
    return 0;
}
/*

*/

 

 

 

以上是关于[SDOI2016]征途的主要内容,如果未能解决你的问题,请参考以下文章

[SDOI2016]征途

bzoj4518[Sdoi2016]征途 斜率优化dp

[SDOI2016]征途

luoguP4072 [SDOI2016]征途

BZOJ4518[Sdoi2016]征途 斜率优化

4518: [Sdoi2016]征途|斜率优化