Description

给定一个长度为 \(n\) 的序列,需要将其划分成 \(k+1\) 份,每次划分时会将一个段划分成两个段,本次操作的得分为划分成的两个段的和的乘积。求最大得分和为多少。

Solution

容易证明操作顺序对答案没有影响,具体可以证明个结合律,代数系统里面有过类似的东西。

\(f(i,j)\) 表示前 \(j\) 个数分了 \(i\) 次的最大得分,则显然有转移

\[f(i,j) \leftarrow f(i-1,k) + s_k (s_j-s_k) \]

转化一下,并记 \(f_j = f(i,j), g_j = f(i-1,j)\),则有

\[s_k^2 - g_k = s_j s_k - f_j \]

于是,考虑设 \(Y(k) = s_k^2 - g_k , K(j) = s_j, X(k) = s_k, B(j) = -f_j\),斜率优化即可,维护一个斜率单调递增的单调队列。

自闭原因:数组大小写反,卡精度

#include <bits/stdc++.h>
using namespace std;

#define int long long 
#define double long double
const int N = 100005;
const int M = 205;

int n,k,a[N],s[N],q[N],f[N],g[N],head=0,tail=0;
int from[M][N];

double Y(int k)
{
    return s[k]*s[k]-g[k];
}
double X(int k)
{
    return s[k];
}
double K(int j)
{
    return s[j];
}
double B(double Y,double K,double X)
{
    return Y-K*X;
}



double slope(int p,int q)
{
    double dy=Y(p)-Y(q);
    double dx=X(p)-X(q);
    if(abs(dx)<1e-9)
    {
        return -1e32;
    }
    else 
    {
        return dy/dx;
    }
}

signed main()
{
    // freopen("p3648.in","r",stdin);

    ios::sync_with_stdio(false);

    cin>>n>>k;
    for(int i=1;i<=n;i++) cin>>a[i];

    for(int i=1;i<=n;i++) s[i]=s[i-1]+a[i];

    for(int i=1;i<=k;i++)
    {
        for(int j=1;j<=n;j++) g[j]=f[j];
        head=0;
        tail=-1;
        q[0]=0;
        for(int j=1;j<=n;j++)
        {
            while(head<tail && slope(q[head],q[head+1])<=K(j)) ++head;
            if(head<=tail)
            {
                int k=q[head];
                f[j]=g[k]+s[k]*(s[j]-s[k]);
                from[i][j]=k;
            }
            else f[j]=0;
            while(head<tail && slope(q[tail-1],q[tail])>=slope(q[tail],j)) --tail;
            q[++tail]=j;

        }
    }

    cout<<f[n]<<endl;

    int i=k, j=from[k][n];
    while(i)
    {
        cout<<j<<" ";
        j=from[--i][j];
    }
}

相关文章:

  • 2021-08-25
  • 2022-01-01
  • 2022-12-23
  • 2021-09-22
  • 2021-12-29
  • 2021-12-18
  • 2021-10-16
  • 2022-03-04
猜你喜欢
  • 2021-11-23
  • 2022-02-16
  • 2021-08-21
  • 2021-07-18
  • 2022-01-18
  • 2021-12-01
  • 2021-06-27
相关资源
相似解决方案