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. http协议详解(2)

    HTTP报文是面向文本的,报文中的每一个字段都是一些ASCII码串,各个字段的长度是不确定的.HTTP有两类报文:请求报文和响应报文. HTTP请求报文 一个HTTP请求报文由请求行(request ...

  2. c++ 类初始化

    一. 成员初始化列表的位置. 成员初始化列表的位置位于构造函数的函数体和参数表之间.构造函数初始化列表以一个冒号开始,接着是以逗号分隔的数据成员列表,每个数据成员后面跟一个放在括号中的初始化式,初始化 ...

  3. JZOJ.5246【NOIP2017模拟8.8】Trip

    Description        多年之后,worldwideD厌倦竞争,隐居山林.       他的家乡开始发展起了旅游业,在一条很长的主干道上,有N个旅游景点,按顺序编号为1到N.根据游客们网 ...

  4. 【BZOJ3714】[PA2014]Kuglarz 最小生成树

    [BZOJ3714][PA2014]Kuglarz Description 魔术师的桌子上有n个杯子排成一行,编号为1,2,…,n,其中某些杯子底下藏有一个小球,如果你准确地猜出是哪些杯子,你就可以获 ...

  5. 转载别人的DLL DEll研究

    昨日,编了个DLL和EXE来进行了下测试,exe通过lib静态联编dll,来调用它的导出类,当改变DLL中导出类的结构(eg.成员变量的顺序等),从新发布DLL而不从新联结编译EXE,就会造成错误的执 ...

  6. JDK源码分析之concurrent包(三) -- Future方式的实现

    上一篇我们基于JDK的源码对线程池ThreadPoolExecutor的实现做了分析,本篇来对Executor框架中另一种典型用法Future方式做源码解读.我们知道Future方式实现了带有返回值的 ...

  7. Sublime text找不到.so文件

    在使用Sublime text打开一个android项目的时候,你会发现找不到.so文件. 解决方法: 点击Sublime text的Preferences,然后点击Settings,这时候出现设置的 ...

  8. Design Pattern – Proxy, Adapter, Facade, Mediator

    这几个模式比较类似, 都是用作interface, 但有所不同 Proxy, 特点是以假乱真, client在使用的时候就和在使用真正的object一样, 接口完全一致, proxy和object的交 ...

  9. I/O多路复用技术(multiplexing)是什么?

    作者:知乎用户链接:https://www.zhihu.com/question/28594409/answer/52763082来源:知乎著作权归作者所有.商业转载请联系作者获得授权,非商业转载请注 ...

  10. shell function/for in/for (())/string concat/has dir/rename using regex/if(())/exit/execute command and pass value to variable/execute python

    #!/bin/bash #remove the MER.*_ in file name for all the files in a dir function getdir(){ for elemen ...