首先看这个得分方式,容易发现就相当于分k段,每段的值和两两乘起来。

这样就很容易列出dp方程:设f[i][j]为到j分成分成i段,转移是

\[f[i][j]=max { f[k][j]+s[k]*(s[j]-s[k]) }
\]

然后显然这个可以斜率优化,随便推一推式子,假设k选p大于选q,那么

\[f[p][j]+s[p]*(s[j]-s[p])>f[q][j]+s[q]*(s[j]-s[q])
\]

\[f[p][j]+s[p]*s[j]-s[p]^2>f[q][j]+s[q]*s[j]-s[q]^2
\]

\[f[p][j]-f[q][j]-s[p]^2+s[q]^2>s[j]*(s[q]-s[p])
\]

\[\frac{f[p][j]-f[q][j]-s[p]^2+s[q]^2}{s[q]-s[p]}>s[j]
\]

维护一个斜率单调的队列即可。

注意s[q]-s[p]可能是0,所以要特判一下

#include<iostream>
#include<cstdio>
using namespace std;
const int N=100005;
int n,m,to[205][N],q[N];
long long s[N],f[2][N];
int read()
{
int r=0,f=1;
char p=getchar();
while(p>'9'||p<'0')
{
if(p=='-')
f=-1;
p=getchar();
}
while(p>='0'&&p<='9')
{
r=r*10+p-48;
p=getchar();
}
return r*f;
}
inline double wk(int r,int j,int k)
{
if(s[j]==s[k])
return -1e18;
return (f[r&1^1][k]-s[k]*s[k]-f[r&1^1][j]+s[j]*s[j])*1.0/(s[j]-s[k]);
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)
s[i]=s[i-1]+read();
for(int i=1;i<=m;i++)
{
int l=0,r=0;
for(int j=1;j<=n;j++)
{
while(l<r&&wk(i,q[l],q[l+1])<=s[j])
l++;
to[i][j]=q[l];
f[i&1][j]=f[(i&1)^1][q[l]]+s[q[l]]*(s[j]-s[q[l]]);
while(l<r&&wk(i,q[r-1],q[r])>=wk(i,q[r],j))
r--;
q[++r]=j;
}
}
printf("%lld\n",f[m&1][n]);
for(int i=m,u=n;i>=1;i--)
{
u=to[i][u];
printf("%d ",u);
}
return 0;
}#include<iostream>
#include<cstdio>
using namespace std;
const int N=100005;
int n,m,to[205][N],q[N];
long long s[N],f[2][N];
int read()
{
int r=0,f=1;
char p=getchar();
while(p>'9'||p<'0')
{
if(p=='-')
f=-1;
p=getchar();
}
while(p>='0'&&p<='9')
{
r=r*10+p-48;
p=getchar();
}
return r*f;
}
inline double wk(int r,int j,int k)
{
if(s[j]==s[k])
return -1e18;
return (f[r&1^1][k]-s[k]*s[k]-f[r&1^1][j]+s[j]*s[j])*1.0/(s[j]-s[k]);
}
int main()
{
n=read(),m=read();
for(int i=1;i<=n;i++)
s[i]=s[i-1]+read();
for(int i=1;i<=m;i++)
{
int l=0,r=0;
for(int j=1;j<=n;j++)
{
while(l<r&&wk(i,q[l],q[l+1])<=s[j])
l++;
to[i][j]=q[l];
f[i&1][j]=f[(i&1)^1][q[l]]+s[q[l]]*(s[j]-s[q[l]]);
while(l<r&&wk(i,q[r-1],q[r])>=wk(i,q[r],j))
r--;
q[++r]=j;
}
}
printf("%lld\n",f[m&1][n]);
for(int i=m,u=n;i>=1;i--)
{
u=to[i][u];
printf("%d ",u);
}
return 0;
}

最新文章

  1. 【PostgreSQL】PostgreSQL添加新服务器连接时,报错“Server doesn&#39;t listen ”,已解决。
  2. javascript面向对象(一):封装
  3. Integer.valueof(null)报错
  4. Effective Java 学习笔记之所有对象都通用的方法
  5. JVM-class文件完全解析-属性表集合
  6. ubuntu NTP server 搭建
  7. Tableview的更新和删除某一行
  8. 【BZOJ】1798: [Ahoi2009]Seq 维护序列seq(线段树)
  9. 批处理+VBS+注册表实现开机自动启动EXE程序
  10. 将dataset写入数据库
  11. html5 spring demo
  12. Android MediaPlayer播放一般音频与SoundPool播放短促的音效
  13. golang protobuf
  14. 检索算法 -- 数据结构与算法的javascript描述 第13章
  15. A Game of Thrones(2) - Catelyn
  16. MySQL搭建主从数据库 实现读写分离
  17. Android 5.0 调色 Palette调色功能
  18. 原生js开发vue的双向数据绑定
  19. Python中Celery 的基本用法以及Django 结合 Celery 的使用和实时监控进程
  20. kaggle竞赛-保险转化-homesite

热门文章

  1. 2016 ACM-ICPC CHINA-Final
  2. 实验二:编写输出“Hello word!”
  3. iOS: 解决Asset Catalog Compile Error - TDDIstiller instance can only be distilled only one time的错误
  4. 【C#】无损转换Image为Icon 【C#】组件发布:MessageTip,轻快型消息提示窗 【C#】给无窗口的进程发送消息 【手记】WebBrowser响应页面中的blank开新窗口及window.close关闭本窗体 【手记】调用Process.EnterDebugMode引发异常:并非所有引用的特权或组都分配给呼叫方 【C#】DataRowState演变备忘
  5. 找中位数O(n)算法
  6. TestNg的工厂測试引用@DataProvider数据源----灵活使用工厂測试
  7. 多媒体开发之wis-stream
  8. Flex+Java+Blazeds
  9. Hackrank Candies DP
  10. slf4j的总结