洛谷P3648 [APIO2014]序列分割(斜率优化)
没想到这种多个状态转移的还能用上斜率优化……学到了……
首先我们可以发现,切的顺序对最终答案是没有影响的
比方说有一个序列$abc$,每一个字母都代表几个数字,那么先切$ab$再切$bc$,得分是$ab+bc+ac$,而如果先切$bc$再切$ab$,得分也是$ab+bc+ac$,不难看出得分是一样的
那么我们可以考虑一下转移方程$$dp[a][i]=max\{dp[a-1][j]+sum[j]*(sum[i]-sum[j])\}$$
其中$a$表示切几刀,$sum$表示前缀和
然后发现空间复杂度太大了,又发现每一刀的状态只与前一刀有关,那么可以用滚动数组优化
然后上面的转移是$O(n^2k)$的,那么考虑用斜率优化优化到$O(nk)$(以下省略dp的第一维)
我们假设$j>k$且$j$比$k$更优,则有$$dp[j]+sum[j]*(sum[i]-sum[j])>dp[k]+sum[k]*(sum[i]-sum[k])$$
$$(dp[j]-sum[j]^2)-(dp[k]-sum[k]^2)>sum[i]*sum[k]-sum[i]*sum[j]$$
因为$sum[k]-sum[j]$是负数,所以除的时候不等式要变号
$$\frac{(dp[j]-sum[j]^2)-(dp[k]-sum[k]^2)}{sum[k]-sum[j]}<sum[i]$$
然后直接上斜率优化
注意特判$sum[k]-sum[j]=0$,随便返回极大值或极小值
顺便注意记录路径
//minamoto
#include<iostream>
#include<cstdio>
#define ll long long
using namespace std;
#define getc() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++)
char buf[<<],*p1=buf,*p2=buf;
inline int read(){
#define num ch-'0'
char ch;bool flag=;int res;
while(!isdigit(ch=getc()))
(ch=='-')&&(flag=true);
for(res=num;isdigit(ch=getc());res=res*+num);
(flag)&&(res=-res);
#undef num
return res;
}
char sr[<<],z[];int C=-,Z;
inline void Ot(){fwrite(sr,,C+,stdout),C=-;}
inline void print(int x){
if(C><<)Ot();if(x<)sr[++C]=,x=-x;
while(z[++Z]=x%+,x/=);
while(sr[++C]=z[Z],--Z);sr[++C]=' ';
}
const int N=;
int to[][N],q[N],n,k,h,t,r;
ll sum[N],dp[][N];
inline double slope(int j,int k){
if(sum[j]==sum[k]) return 1e18;
return ((dp[r^][j]-sum[j]*sum[j])-(dp[r^][k]-sum[k]*sum[k]))*1.0/(sum[k]-sum[j]);
}
int main(){
//freopen("testdata.in","r",stdin);
n=read(),k=read();
for(int i=;i<=n;++i) sum[i]=read()+sum[i-];
for(int a=;a<=k;++a){
r=a&;
h=t=;
for(int i=;i<=n;++i){
while(h<t&&slope(q[h],q[h+])<sum[i]) ++h;
to[a][i]=q[h];
dp[r][i]=dp[r^][q[h]]+sum[q[h]]*(sum[i]-sum[q[h]]);
while(h<t&&slope(q[t],q[t-])>slope(q[t-],i)) --t;q[++t]=i;
}
}
printf("%lld\n",dp[k&][n]);
for(int i=k,u=n;i;--i){
u=to[i][u];
print(u);
}
Ot();
return ;
}
洛谷P3648 [APIO2014]序列分割(斜率优化)的更多相关文章
- 洛谷 P3648 [APIO2014]序列分割 解题报告
P3648 [APIO2014]序列分割 题目描述 你正在玩一个关于长度为\(n\)的非负整数序列的游戏.这个游戏中你需要把序列分成\(k+1\)个非空的块.为了得到\(k+1\)块,你需要重复下面的 ...
- 洛谷 P3648 [APIO2014]序列分割
题意简述 有一个长度为n的序列,分成k + 1非空的块, 选择两个相邻元素把这个块从中间分开,得到两个非空的块. 每次操作后你将获得那两个新产生的块的元素和的乘积的分数.求总得分最大值. 题解思路 f ...
- P3648 [APIO2014]序列分割 斜率优化
题解:斜率优化\(DP\) 提交:\(2\)次(特意没开\(long\ long\),然后就死了) 题解: 好的先把自己的式子推了出来: 朴素: 定义\(f[i][j]\)表示前\(i\)个数进行\( ...
- bzoj3675[Apio2014]序列分割 斜率优化dp
3675: [Apio2014]序列分割 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 3508 Solved: 1402[Submit][Stat ...
- [APIO2014]序列分割 --- 斜率优化DP
[APIO2014]序列分割 题目大意: 你正在玩一个关于长度为\(n\)的非负整数序列的游戏.这个游戏中你需要把序列分成\(k+1\)个非空的块.为了得到\(k+1\)块,你需要重复下面的操作\(k ...
- 洛谷3648 [APIO2014]序列分割(斜率优化+dp)
首先对于这个题目. qwq 存在一个性质就是,最终的答案只跟你的分割的位置有关,而和顺序无关. 举一个小栗子 \(a\ b\ c\) 将这个东西分成两块. 如果我们先分割\(ab\)之间的话,\(an ...
- BZOJ3675: [Apio2014]序列分割(斜率优化)
Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 4186 Solved: 1629[Submit][Status][Discuss] Descript ...
- 【bzoj3675】[Apio2014]序列分割 斜率优化dp
原文地址:http://www.cnblogs.com/GXZlegend/p/6835179.html 题目描述 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列 ...
- BZOJ 3675 [Apio2014]序列分割 (斜率优化DP)
洛谷传送门 题目大意:让你把序列切割k次,每次切割你能获得 这一整块两侧数字和的乘积 的分数,求最大的分数并输出切割方案 神题= = 搞了半天也没有想到切割顺序竟然和答案无关...我太弱了 证明很简单 ...
随机推荐
- How far away ?(LCA)dfs和倍增模版
How far away ? Tarjan http://www.cnblogs.com/caiyishuai/p/8572859.html Time Limit: 2000/1000 MS (Jav ...
- canvas绘制中的API
canvas绘制Z 先贴代码吧: /** * Created by Administrator on 2016/1/26. */ var i; function draw (id){ var canv ...
- HTTP-Runoob:HTPP消息结构
ylbtech-HTTP-Runoob:HTPP消息结构 1.返回顶部 1. HTTP 消息结构 HTTP是基于客户端/服务端(C/S)的架构模型,通过一个可靠的链接来交换信息,是一个无状态的请求/响 ...
- 分布式代码管理github
Git是世界上最先进的分布式版本的控制系统,特点是:简单大气上档次. Linus在1991年创建了开源的Linux,从此,Linux系统不断发展,已经成为最大的服务器系统软件了.
- vi,sed,tr,awk技巧
将文件中的换行替换为逗号 使用sed: sed -e :a -e N -e '$!ba' -e 's/\n/,/g' filename 使用tr: cat filename | tr '\n' ',' ...
- apache http 跳到https
RewriteEngine OnRewriteCond %{HTTPS} !=onRewriteRule ^(.*) https://%{SERVER_NAME}/$1 [R,L]
- Mediaplayer
Mediaplayer报错 prepareAsync called in state 1 是因为在setDataSource之前调用了prepare.因为setDataSource放到了线程里 ...
- to_date() 、to_char()、to_number的FMT格式
元素 含义 结果:2018/01/12(周五) - / , . ; : (6中不同分隔符) 分隔符 y 显示一位年份 8 yy 显示二位年 ...
- 【摘自张宴的"实战:Nginx"】使用nginx的fastcgi_cache缓存php输出的内容
亲自测试发现,fastcgi_cache虽然可以缓存生成的php输出的文件,但是有个弊端,在缓存的失效时间之内,你继续访问这个地址,输出的内容没有发生变化,即使数据库新增了数据或者删除了数据,所以不适 ...
- c# json.net xml互转
json转xml: XmlDocument doc = (XmlDocument)JsonConvert.DeserializeXmlNode(jsonText,"root"); ...