bzoj3675 [Apio2014]序列分割

傳送門

好久都沒寫blog了啊。。。主要是懶。。。

今天做了幾道斜率優化dp題,感覺這是最有價值的一道,發出來存一下。。。

首先題目要求將一個序列劃分k次,一次劃分的貢獻是被劃分出兩部分的乘積。有一個結論:切的先後沒有影響。。果然猜結論是一種很重要的能力= =
然後就可以化式子斜率優化了,,,注意滾動數組的細節!

CODE:

#include<cstdio>
#define N 100005
typedef long long ll;
int q[N],h,t;
ll f[N][2],a[N];
int n,k,tot;
inline double sqr(double x){return x*x;}
inline double slope(int i,int j,int wh){return (double)(f[i][wh^1]-f[j][wh^1]+sqr(a[j])-sqr(a[i]))/(double)(a[j]-a[i]);}
int main()
{
    scanf("%d%d",&n,&k);
    for(int i=1;i<=n;i++)
      scanf("%lld",&a[i]);
    for(int i=1;i<=n;i++)
      if(a[i]) a[++tot]=a[i];
    n=tot;
    for(int i=1;i<=n;i++)
      a[i]+=a[i-1];
    for(int j=1;j<=k;j++)
    {
        h=t=0;q[0]=j-1;
        for(int i=j;i<=n;i++)
        {
            while(h<t&&slope(q[h],q[h+1],j&1)<a[i]) h++;
            f[i][j&1]=f[q[h]][~j&1]+a[q[h]]*(a[i]-a[q[h]]);
            while(h<t&&slope(q[t-1],q[t],j&1)>slope(q[t],i,j&1)) t--;
            q[++t]=i;
        }
    }
    printf("%lld",f[n][k&1]);
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章