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. VS2010程序打包操作(结合图片详细讲解)

     附视频教程:http://www.cnblogs.com/mengdesen/archive/2011/06/14/2080312.html 1.  在vs2010 选择“新建项目”----“其他项 ...

  2. linux一台机器文件传到另一台机器上

    登录一台机器35.73: scp -P 端口 要传的文件 user@xxx.xxx.xxx.xxx:/目标文件夹/ 例子 :scp -r -P3561 /home/ismp/build/app/bec ...

  3. Less-Mixins分离规则集

    //Mixins --立即执行函数 .test{/* */} #test{/* */} --指定执行函数 .test(){/* */} #test(){/* */} --调用: .test; or . ...

  4. Less-mixin函数基础二

    //mixin函数 基础使用方法 --包含选择器,example: .test(){ &:hover{ border:1px solid red; } } button{ .test; } / ...

  5. Jupyter Notebook远程服务器配置

    首先要生成密码,打开python终端. In [1]: from IPython.lib import passwd In [2]: passwd() Enter password: Verify p ...

  6. iOS中nil 、NULL、 Nil 、NSNull

    nil,定义一个空的实例,指向OC中对象的空指针. 示例代码: NSString *someString = nil; NSURL *someURL = nil; id someObject = ni ...

  7. <2014 05 09> 程序员:从C++转到Java需注意的地方

    最近想玩玩Android的APP开发,从C++角度来学习Java.Java可以说是一个优化精简版的C++,去除了底层C的很多特性.找了这篇文章. --------------------------- ...

  8. Python菜鸟之路:Django 信号

    Django中提供了“信号调度”,用于在框架执行操作时解耦.通俗来讲,就是一些动作发生的时候,信号允许特定的发送者去提醒一些接受者. 相当于我们创建了一个hook. 1. Django的内置信号 Mo ...

  9. rest_framework 响应器

    一 作用 根据 用户请求URL 或 用户可接受的类型,筛选出合适的 渲染组件.用户请求URL:    http://127.0.0.1:8000/test/?format=json    http:/ ...

  10. HTTP协议简要介绍

    1. 网络基础 TCP/IP 通常使用的网络是在TCP/IP协议簇基础上运作的. HTTP属于它内部的一个子集. TCP/IP分为4个层次, 应用层, 传输层, 网络层, 链路层. (Applicat ...