首先看这个得分方式,容易发现就相当于分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;
}

bzoj 3675: [Apio2014]序列分割【斜率优化dp】的更多相关文章

  1. BZOJ 3675 [Apio2014]序列分割 (斜率优化DP)

    洛谷传送门 题目大意:让你把序列切割k次,每次切割你能获得 这一整块两侧数字和的乘积 的分数,求最大的分数并输出切割方案 神题= = 搞了半天也没有想到切割顺序竟然和答案无关...我太弱了 证明很简单 ...

  2. BZOJ 3675 APIO2014 序列切割 斜率优化DP

    题意:链接 方法:斜率优化DP 解析:这题BZ的数据我也是跪了,特意去网上找到当年的数据后面二十个最大的点都过了.就是过不了BZ. 看到这道题自己第一发DP是这么推得: 设f[i][j]是第j次分第i ...

  3. bzoj3675[Apio2014]序列分割 斜率优化dp

    3675: [Apio2014]序列分割 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 3508  Solved: 1402[Submit][Stat ...

  4. [APIO2014]序列分割 --- 斜率优化DP

    [APIO2014]序列分割 题目大意: 你正在玩一个关于长度为\(n\)的非负整数序列的游戏.这个游戏中你需要把序列分成\(k+1\)个非空的块.为了得到\(k+1\)块,你需要重复下面的操作\(k ...

  5. 【bzoj3675】[Apio2014]序列分割 斜率优化dp

    原文地址:http://www.cnblogs.com/GXZlegend/p/6835179.html 题目描述 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列 ...

  6. BZOJ 3675: [Apio2014]序列分割( dp + 斜率优化 )

    WA了一版... 切点确定的话, 顺序是不会影响结果的..所以可以dp dp(i, k) = max(dp(j, k-1) + (sumn - sumi) * (sumi - sumj)) 然后斜率优 ...

  7. 【斜率DP】BZOJ 3675:[Apio2014]序列分割

    3675: [Apio2014]序列分割 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 1066  Solved: 427[Submit][Statu ...

  8. P3648 [APIO2014]序列分割 斜率优化

    题解:斜率优化\(DP\) 提交:\(2\)次(特意没开\(long\ long\),然后就死了) 题解: 好的先把自己的式子推了出来: 朴素: 定义\(f[i][j]\)表示前\(i\)个数进行\( ...

  9. BZOJ 3675 [Apio2014]序列分割 (斜率优化DP)

    题目链接 BZOJ 3675 首先最后的答案和分割的顺序是无关的, 那么就可以考虑DP了. 设$f[i][j]$为做了$i$次分割,考虑前$j$个数之后的最优答案. 那么$f[i][j] = max( ...

随机推荐

  1. POJ 2749 2SAT判定+二分

    题意:图上n个点,使每个点都与俩个中转点的其中一个相连(二选一,典型2-sat),并使任意两点最大 距离最小(最大最小,2分答案),有些点相互hata,不能选同一个中转点,有些点相互LOVE,必需选相 ...

  2. [Android] 通过GridView仿微信动态添加本地图片

    原文:http://blog.csdn.net/eastmount/article/details/41808179 前面文章讲述的都是"随手拍"中图像处理的操作,此篇文章主要讲述 ...

  3. Delphi:解决重绘造成的窗体闪烁问题

    解决窗体闪烁问题 具体代码: 1.在声明窗体类时加入:   private     procedure CreateParams(var Params: TCreateParams); overrid ...

  4. D. Spongebob and Squares--cf599D(数学)

    http://codeforces.com/problemset/problem/599/D 题目大意:给你一个数k  让你求一个n*m的矩形里面包含k个正方形   输出有几个这样的矩形  分别是什么 ...

  5. 2017-10-04-morning

    改题面只有1改为0 .. #include <cstring> #include <cstdio> inline void read(int &x) { x=; reg ...

  6. AtCoder Regular Contest 091&092

    091E(构造) 题意: 给出n,a,b.你需要构造出一个长度为n的n的排列,其中最长上升子序列的长度为a,最长下降子序列的长度为b. n,a,,b<=3e5 分析: 我们可以构造出这样的数列, ...

  7. JVM(零):走入JVM

    JVM(零):走入JVM 本系列主要讲述JVM相关知识,作为本系列的第一篇文章,本文从Java为什么是一个跨平台的语音开始介绍,逐步引入Java虚拟机的概念,并给出一个JVM相关知识图谱,可以让读者从 ...

  8. 【Nginx】请求上下文

    上下文与全异步web服务器的关系 请求上下文指在一个请求的处理过程中,把一些关键的信息保存下来的类似struct这样的结构体.每个http模块都可以有自己的上下文结构体,一般都是在刚开始处理请求时在内 ...

  9. Python第五讲

    一.冒泡算法 1.将两个变量的值互换 a1 = 123 a2 = 456 #要想将a1与a2的值进行位置互换需要借助一个中间变量(temp) temp = a1#将a1的值赋值给temp(temp=1 ...

  10. springMVC4(16)拦截器解析与登陆拦截模拟

    在SpringMVC中,我们会常常使用到拦截器,尽管SpringAOP也能帮我们实现强大的拦截器功能,但在Web资源供给上.却没有SpringMVC来得方便快捷. 使用SpringMVC拦截器的核心应 ...