原文链接http://www.cnblogs.com/zhouzhendong/p/8697258.html

题目传送门 - BZOJ3675

题意

  对于一个非负整数序列,小H需要重复k次以下的步骤:

  1.选择一个长度超过1的序列

  2.从任意位置将序列分割成两个非空的新序列。

  每次,小H将会得到分数。分数为两个新序列中元素和的乘积。请选择一种最佳的分割方式,使得k轮之后,使总得分最大。输出总得分。

  $n\leq 10^5,k\leq min(n-1,200)$

题解

  真是一道不错的题目。

  首先,我们要发掘一个性质。

对于一个最终的划分方案,以各种不同顺序划分,所得到的得分总是相同。

  设两个区间和做乘积并累加到答案里的过程为这两个区间对答案做了一次贡献。

  那么我们要证明划分完毕之后,任意两个连续区间都互相做了且仅互相做了一次贡献。

  考虑每次划分大区间的时候,划分出来的左边和右边每一个区间都做了贡献,而显然之后在左边的就不会和右边做贡献了,于是任意两个连续区间最多做一次贡献。

  考虑到对于子区间,我们不断进行子区间的左右子区间互相贡献,直到划分为1为止。

  可以感性理解一下,每一个最终区间一定会和其他所有最终区间贡献。

  或者也可以用一个更简易的证明:

  |s1|s2|s3|

  考虑以上的3段区间,区间和分别为s1,s2,s3,你可以自己试着先割s1和s2以及先割s2和s3,然后你会发现最后算出来的结果是相同的。

  所以我们可以从左到右分割。

  于是我们可以写出DP方程。

  $dp_{r,i}$表示分割了$r$次,分割到了$i$这个位置。

  设$sum_i=\sum_{j=1}^i a_j$。

  $$dp_{r,i}=max\{dp_{r-1,j}+sum_j(sum_i-sum_j)\}\ \ \ (0\leq j<i)$$

  显然可以斜率优化。

  稍微推导一下:

  $$dp_{r-1,j}+sum_j(sum_i-sum_j)\\=dp_{r-1,j}-sum_j^2+sum_jsum_i$$

  令

  $$x_i=sum_i$$

  $$y_i=dp_{r-1,i}-sum_i^2$$

  则原式=

  $$y_j+sum_ix_j$$

  假设$j>k$且从$j$转移不劣于$k$,则:

  $$y_j+sum_ix_jy_k+sum_ix_k$$

  化简得:

  $$\frac{y_j-y_k}{x_j-x_k}\geq -sum_i$$

  然后献上又一波斜率优化DP套路:

  注意由于开始限制了$j>k$所以$x_j-x_k>0$,所以最后两边同时相除不等式仍然成立。

  设

  $$g_{i,j}=\frac{y_i-y_j}{x_i-x_j}\ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ \ (i>j)$$

  则上式可以表示为$g_{j,k}\geq -sum_i$

  我们来发掘以下$g_{j,k}$的性质。

  1. 当$g_{j,k}\geq -sum_i$时,由于随着$i$变大,$-sum_i$变小,所以显然从$k$转移是永远不会比$j$好的,所以我们可以把$k$扔掉。

  2. 当$g_{i,j}\geq g_{j,k}$时,从$i$或者$k$转移至少有一个不比$j$差,所以可以把$j$扔掉。为什么??

    若$g_{i,j}\geq -sum_i$,显然$j$要被扔掉,根据第一个性质。

    若$g_{i,j}<-sum_i$,则$g_{j,k}<-sum_i$,那么显然$j$比$k$差,也得被扔掉。

  于是我们可以用一个单调队列来维护斜率的单调性。

  具体的:

  当情况1发生的时候让队首出队。

  在进队的时候,如果发生情况2,那么先让队尾出队,然后再进队。

  为了避免精度问题,以及分母为0的问题,我们可以把$x_i-x_j$乘上来,用乘积式来判断大小。

  但是本题空间限制较为紧。

  所以要滚动。

  注意初始化还没有进行任何一次分割时候的$x_i,y_i$,我一开始还以为都是0,调了很久。

代码

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
const int N=100005;
int n,R,q[N],head,tail;
LL sum[N],x[2][N],y[2][N],dp[2][N];
int main(){
scanf("%d%d",&n,&R);
for (int i=1;i<=n;i++)
scanf("%lld",&sum[i]),sum[i]+=sum[i-1];
int T0=1,T1=0;
for (int i=1;i<=n;i++)
x[T1][i]=sum[i],y[T1][i]=-sum[i]*sum[i];
for (int r=1;r<=R;r++){
T0^=1,T1^=1;
head=1,tail=0;
q[++tail]=0;
for (int i=1;i<=n;i++){
int j=q[head+1],k=q[head];
while (tail-head>0&&y[T0][j]-y[T0][k]>=(x[T0][j]-x[T0][k])*(-sum[i]))
head++,j=q[head+1],k=q[head];
j=k;
dp[T1][i]=dp[T0][j]+sum[j]*(sum[i]-sum[j]);
x[T1][i]=sum[i];
y[T1][i]=dp[T1][i]-sum[i]*sum[i];
j=q[tail],k=q[tail-1];
while (tail-head>0&&(y[T0][i]-y[T0][j])*(x[T0][j]-x[T0][k])>=(y[T0][j]-y[T0][k])*(x[T0][i]-x[T0][j]))
tail--,j=q[tail],k=q[tail-1];
q[++tail]=i;
}
}
printf("%lld",dp[T1][n]);
return 0;
}

  

BZOJ3675 [Apio2014]序列分割 动态规划 斜率优化的更多相关文章

  1. [Bzoj3675][Apio2014]序列分割(斜率优化)

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

  2. BZOJ3675 [Apio2014]序列分割 【斜率优化dp】

    3675: [Apio2014]序列分割 Time Limit: 40 Sec  Memory Limit: 128 MB Submit: 3366  Solved: 1355 [Submit][St ...

  3. 2018.09.29 bzoj3675: [Apio2014]序列分割(斜率优化dp)

    传送门 斜率优化dp经典题目. 首先需要证明只要选择的K个断点是相同的,那么得到的答案也是相同的. 根据分治的思想,我们只需要证明有两个断点时成立,就能推出K个断点时成立. 我们设两个断点分成的三段连 ...

  4. BZOJ3675 Apio2014 序列分割 【斜率优化】

    Description 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列.为了得到k+1个子序列,小H需要重复k次以下的步骤: 1.小H首 ...

  5. BZOJ 3675: [Apio2014]序列分割 动态规划 + 斜率优化 + 卡精度

    Code: #include<bits/stdc++.h> #define N 100006 #define M 205 #define ll long long #define setI ...

  6. 【BZOJ3675】序列分割(斜率优化,动态规划)

    [BZOJ3675]序列分割(斜率优化,动态规划) 题面 Description 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列.为了得 ...

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

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

  8. 【BZOJ-3675】序列分割 DP + 斜率优化

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

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

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

随机推荐

  1. MS SqlServer还原数据库,出现媒体簇的结构不正确

    出现此问题,是数据库版本过低导致,只要保证连接实例所在的版本号>=要还原的数据库的版本号,即可还原成功. 可以使用select @@VERSION,查看当前实例版本.

  2. Windows服务没有及时响应启动或控制请求1053

    参考链接: 解决“指定的服务已经标记为删除”问题 服务没有及时响应启动或控制请求 1053 关闭服务后,重新启动windows服务报错:"服务没有及时响应启动或控制请求 1053" ...

  3. LA 4108 (线段树)

    区间更新 + 统计更新长度 稍稍不注意就T了 #include<bits/stdc++.h> #define lson l, m, rt<<1 #define rson m+1 ...

  4. 文本内容查找grep、文件查找find、正则匹配

    一.文本内容查找工具 grep grep   egrep (文本过滤)   fgrep (不支持正则) 对文本的内容按照指定的匹配模式基于行来进行筛选 格式     grep [选项] 模式 文件 选 ...

  5. JS实现图片放大查看

    示例:https://wumaozheng.com/static-pages/image-magnifier.html <!DOCTYPE html> <html> <h ...

  6. Confluence 6 缓存性能示例

    有关 Confluence 的缓存性能如何设置,让我们看看下面的表: 缓存(Caches) % 使用的缓存(Used) % 有效率(Effectiveness) 对象/大小(Objects/Size) ...

  7. Confluence 6 字符集编码的问题解决

    如果你的 Confluence 站点的字符集没有被正确配置,你可能会遇到下面的问题: Non-ASCII 字符将会显示为问号(?) Non-ASCII 字符集的页面链接将不能工作 单一字符将会被显示为 ...

  8. linux 下创建共享文件夹

    首先需要在win下共享一个盘 然后设置virtulbox 然后修改一串代码 参考原文 https://jingyan.baidu.com/article/2fb0ba40541a5900f2ec5f0 ...

  9. Python基础之面向过程编程

    要求:在文件里递归找到关于包含“Python”内容的文件的绝对路径并打印出来 #定义阶段 import os,time def init(func): #装饰器的作用是使下面的生成器初始化,yield ...

  10. jsp 标签文件

    一. tag file 简介 tag file从两个方面简化了自定义标签的开发.首 先,tag file无须提前编译,直到第一次被调用才会编 译.除此之外,仅仅使用JSP语法就可以完成标签的扩 展定义 ...