Luogu-3648 [APIO2014]序列分割

题目链接

题解:

首先要发现一个重要的性质:分割的顺序是不会影响答案的

证明:

首先对于没有交的两段区间,显然先后顺序改变不会有影响

而对于在同一段区间上的两次分割:

设有一段序列由长度为\(x,y,z\)的三段拼接起来

如果先分割\(xy\)和\(z\),再分割\(x\)和\(y\),答案是\((x+y)*z+x*y\)

而如果先分割\(x\)和\(yz\),再分割\(y\)和\(z\),答案是\(x*(y+z)+y*z\)

可以发现,两个答案都是\(xy+xz+yz\),即分割顺序不影响答案

这样我们就可以愉快地DP啦

设\(f[i][j]\)为将\(1\sim i\)这段分割\(j\)次产生的代价,\(s[i]\)为\(1\sim i\)段的总长,则有:

\[f[i][j]=f[k][j-1]+s[k]*(s[i]-s[k]) \quad k\in [1,i-1]
\]

分割次数这一维可以滚动优化空间,设上一次的为\(g[i]\),这一次要求的是\(f[i]\)

上面的式子就是

\[f[i]=g[k]+s[k]*(s[i]-s[k]) \quad k\in [1,i-1]
\]

哎,感觉很像可以斜率优化的式子啊,那么...

如果从\(k\)转移比从\(j\)转移更优,则:

\[g[k]+s[k]*(s[i]-s[k]) > g[j]+s[j]*(s[i]-s[j])
\]

再化一化

\[\frac{(g[k]+s[k]*s[k])-(g[j]-s[j]*s[j])}{s[j]-s[k]} >s[i]
\]

于是我们就可以用斜率优化dp啦,

注意这题精度卡的简直丧心病狂...算斜率的时候一定要先算减再乘\(1.0\)

代码

#include<map>
#include<queue>
#include<cmath>
#include<bitset>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long ll;
inline ll read(){
ll ans=0,fh=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-') fh=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9')
ans=(ans<<1)+(ans<<3)+ch-'0',ch=getchar();
return ans*fh;
}
const int maxn=1e5+100;
const long double inf=1e18;
int n,k,st[maxn],tp,pre[210][maxn],q[maxn];
ll s[maxn],f[maxn],g[maxn];
inline long double slope(int x,int y){
if(s[x]==s[y]) return -inf;
long double aa=1.0*((g[x]-s[x]*s[x])-(g[y]-s[y]*s[y]));
return aa/(s[y]-s[x]);
}
int main(){
// freopen("nh.in","r",stdin);
//freopen("zhy.out","w",stdout);
n=read(),k=read();
for(int i=1;i<=n;i++) s[i]=read()+s[i-1];
for(int i=1;i<=k;i++){
int l=1,r=0;q[++r]=0;
for(int j=1;j<=n;j++){
while(l<r&&slope(q[l],q[l+1])<=s[j]) l++;
f[j]=g[q[l]]+s[q[l]]*(s[j]-s[q[l]]);
pre[i][j]=q[l];
while(l<r&&slope(q[r-1],q[r])>=slope(q[r],j)) r--;
q[++r]=j;
}
memcpy(g,f,sizeof(g));
}
printf("%lld\n",g[n]);
for(int i=pre[k][n];i;i=pre[--k][i]) st[++tp]=i;
while(tp) printf("%d ",st[tp--]);
return 0;
}

Luogu-3648 [APIO2014]序列分割的更多相关文章

  1. [luogu P3648] [APIO2014]序列分割

    [luogu P3648] [APIO2014]序列分割 题目描述 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列.为了得到k+1个子序 ...

  2. 洛谷3648 [APIO2014]序列分割(斜率优化+dp)

    首先对于这个题目. qwq 存在一个性质就是,最终的答案只跟你的分割的位置有关,而和顺序无关. 举一个小栗子 \(a\ b\ c\) 将这个东西分成两块. 如果我们先分割\(ab\)之间的话,\(an ...

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

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

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

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

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

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

  6. BZOJ_3675_[Apio2014]序列分割_斜率优化

    BZOJ_3675_[Apio2014]序列分割_斜率优化 Description 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列.为了 ...

  7. 斜率优化入门学习+总结 Apio2011特别行动队&Apio2014序列分割&HZOI2008玩具装箱&ZJOI2007仓库建设&小P的牧场&防御准备&Sdoi2016征途

    斜率优化: 额...这是篇7个题的题解... 首先说说斜率优化是个啥,额... f[i]=min(f[j]+xxxx(i,j)) ;   1<=j<i (O(n^2)暴力)这样一个式子,首 ...

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

    P3648 [APIO2014]序列分割 我们先证明,分块的顺序对结果没有影响. 我们有一个长度为3的序列$abc$ 现在我们将$a,b,c$分开来 随意枚举一种分块方法,如$(ab)(c)$,$(a ...

  9. 洛谷 P3648 [APIO2014]序列分割 解题报告

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

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

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

随机推荐

  1. Volley使用详细说明

    前一篇粗略的介绍了一下Volley,并在最后附上了一段使用代码,这一篇详细的介绍一下Volley的使用.前面也说了Volley主要获取JSON对象和图片加载,这里也分为两部分介绍. 1.获取JSON对 ...

  2. git 拉取远程分支到本地并建立关联关系

    git拉取远程分支到本地   一.查看远程分支 使用如下git命令查看所有远程分支: git branch -r   二.拉取远程分支并创建本地分支 方法一 使用如下命令: git checkout ...

  3. Avalondock 第四步 边缘停靠

    前一章介绍了分组功能,这一章主要介绍细节信息,LayoutRoot的side属性 LayoutRoot包含四个属性,LeftSide,RightSide,TopSide,BottomSide,分别用于 ...

  4. Visual Assist X助手的一些使用技巧和快捷键

    部分快捷键 Shift+Alt+F // Find References 查找引用 Shift+Alt+S // FindSynbolDialog打开查找符号对话框 Alt+G // GotoImpl ...

  5. FineReport---函数

    1.NUMTO()需要将数字2345转换成二三四五:NUMTO(2345) 2.Toimage函数:Toimage(path)用于在报表中显示某一路径path下的图片 3.row():为获取当前行号 ...

  6. 让WebApi支持Namespace

    环境:VS2012 .net 4.0 参考: http://aspnet.codeplex.com/SourceControl/changeset/view/dd207952fa86#Samples/ ...

  7. 模块化之SeaJS(一)

    模块化(之SeaJS) 刚接触的童鞋可能会有很多疑惑,比喻:什么是模块?模块的目的是干嘛呀?怎么样实现模块化呢? 不要急,博主正是带着这三个问题来写这篇文章的. 一,什么是模块化? 在前端开发领域,一 ...

  8. 数据库字符集(AL32UTF8)和客户端字符集(2%)是不同的

    登录oracle数据库时我们会遇到这样的提示信息:“数据库字符集(AL32UTF8)和客户端字符集(2%)是不同的”. 这是由于数据库服务端和客户端的字符集不一致所造成的,服务端字符集和客户端字符集相 ...

  9. quartz集群 定时任务 改成可配置

    前面的博文中提到的quartz集群方式会有以下缺点: 1.假设配置了3个定时任务,job1,job2,job3,这时数据库里会有3条job相关的记录,如果下次上线要停掉一个定时任务job1,那即使定时 ...

  10. pandas 如何判断指定列是否(全部)为NaN(空值)

    判断某列是否有NaN df['$open'].isnull().any() # 判断open这一列列是否有 NaN 判断某列是否全部为NaN df['$open'].isnull().all() # ...