3675: [Apio2014]序列分割

Time Limit: 40 Sec  Memory Limit: 128 MB
Submit: 1420  Solved: 583
[Submit][Status][Discuss]

Description

小H最近迷上了一个分隔序列的游戏。在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列。为了得到k+1个子序列,小H需要重复k次以下的步骤:
1.小H首先选择一个长度超过1的序列(一开始小H只有一个长度为n的序列——也就是一开始得到的整个序列);
2.选择一个位置,并通过这个位置将这个序列分割成连续的两个非空的新序列。
每次进行上述步骤之后,小H将会得到一定的分数。这个分数为两个新序列中元素和的乘积。小H希望选择一种最佳的分割方式,使得k轮之后,小H的总得分最大。

Input

输入第一行包含两个整数n,k(k+1≤n)。

第二行包含n个非负整数a1,a2,...,an(0≤ai≤10^4),表示一开始小H得到的序列。

Output

输出第一行包含一个整数,为小H可以得到的最大分数。

Sample Input

7 3
4 1 3 4 0 2 3

Sample Output

108

HINT

【样例说明】 
在样例中,小H可以通过如下3轮操作得到108分: 
1.-开始小H有一个序列(4,1,3,4,0,2,3)。小H选择在第1个数之后的位置 
将序列分成两部分,并得到4×(1+3+4+0+2+3)=52分。 
2.这一轮开始时小H有两个序列:(4),(1,3,4,0,2,3)。小H选择在第3个数 
字之后的位置将第二个序列分成两部分,并得到(1+3)×(4+0+2+3)=36分。 
3.这一轮开始时小H有三个序列:(4),(1,3),(4,0,2,3)。小H选择在第5个 
数字之后的位置将第三个序列分成两部分,并得到(4+0)×(2+3)=20分。 
经过上述三轮操作,小H将会得到四个子序列:(4),(1,3),(4,0),(2,3)并总共得到52+36+20=108分。 
【数据规模与评分】:

数据满足2≤n≤100000,1≤k≤min(n -1,200)。

Source

Solution

个人感觉比较神的题

首先需要发现一个性质:

割k次,只要割的是正确位置,那么答案与割的顺序无关

证明:

大体上假设某串为$abcd$,如果最后要分割成$a|b|cd$那么:

先分割成$ab|cd$当前答案为$a*cd+b*cd$,再分割成$a|b|cd$,答案为$a*b+a*cd+b*cd$

先分割成$a|bcd$当前答案为$a*bcd$,在分割成$a|b|cd$,答案为$a*bcd+b*cd$

那么两式化一化就可以发现得到的是相同的。所以,对于其余的也合适;

那么可以得出一个初步的转移:

$f[i][j]=max(f[j][k-1]+sum[j]*(sum[i]-sum[j]))$其中$f[i][j]$表示的是:前i个元素,分成k段的最大分数

那么可以进行一下斜率优化,最后化出的式子:$(dp[j'][k]-dp[i'][k]+sum[i']*sum[i']-sum[j']*sum[j'])/(sum[i']-sum[j'])<=sum[i]$

有一个额外的处理,如果$a[i]==0$那么它实际上是没有意义的,反而阻碍计算,那么可以直接扔掉

内存有点小,需要滚动数组,那么滚一下就好

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
inline int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define maxn 100010
#define maxk 201
int n,K,a[maxn],que[maxn],l,r;
long long sum[maxn],dp[maxn][];
inline double slope(int i,int j,int k)
{
return double(dp[j][k]-dp[i][k]+sum[i]*sum[i]-sum[j]*sum[j])/double(sum[i]-sum[j]);
}
int main()
{
n=read(),K=read();
for (int i=; i<=n; i++)
{
a[i]=read();
if (a[i]==) {i--; n--; continue;}
sum[i]=sum[i-]+a[i];
}
for (int j=,k=; k<=K; k++,j^=,l=r=)
for (int tmp,i=k; i<=n; i++)
{
while (l<r && slope(que[l],que[l+],j^)<=sum[i]) l++;
tmp=que[l];
dp[i][j]=dp[tmp][j^]+(sum[i]-sum[tmp])*sum[tmp];
while (l<r && slope(que[r-],que[r],j^)>=slope(que[r],i,j^)) r--;
que[++r]=i;
}
printf("%lld\n",dp[n][K&]);
return ;
}

WA了好几次...调了好久QAQ

【BZOJ-3675】序列分割 DP + 斜率优化的更多相关文章

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

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

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

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

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

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

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

    题目链接 BZOJ 3675 首先最后的答案和分割的顺序是无关的, 那么就可以考虑DP了. 设$f[i][j]$为做了$i$次分割,考虑前$j$个数之后的最优答案. 那么$f[i][j] = max( ...

  5. BZOJ 3675: 序列分割 (斜率优化dp)

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

  6. bzoj 3675: [Apio2014]序列分割【斜率优化dp】

    首先看这个得分方式,容易发现就相当于分k段,每段的值和两两乘起来. 这样就很容易列出dp方程:设f[i][j]为到j分成分成i段,转移是 \[ f[i][j]=max { f[k][j]+s[k]*( ...

  7. 【洛谷3648】[APIO2014] 序列分割(斜率优化DP)

    点此看题面 大致题意: 你可以对一个序列进行\(k\)次分割,每次得分为两个块元素和的乘积,求总得分的最大值. 区间\(DPor\)斜率优化\(DP\) 这题目第一眼看上去感觉很明显是区间\(DP\) ...

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

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

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

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

随机推荐

  1. Sonatype Nexus Maven仓库搭建和管理

    安装 1. 从 http://www.sonatype.org/nexus/ 下载最新的 Nexus 压缩包, 现在已经不提供war包的下载 2. 解压到服务器目录, 例如我是放到/opt/nexus ...

  2. Html5 Egret游戏开发 成语大挑战(一)开篇

    最近接触了Egret白鹭引擎,感觉非常好用,提供了各种各样的开发工具让开发者和设计者更加便捷,并且基于typescript语言开发省去了很多学习成本,对于我们这种掉微软坑许久的童鞋来说,确实很有吸引力 ...

  3. 苹果iPhone如何区分港版、国行、水货

    要想分辨所购买的苹果产品[iPhone 4.iPod Touch.iPad 2.iMac.MacBook及iPhone 4S]是大陆行货.水货.港货还是其它,其实很简单.今天来教大家如何区分.大陆行货 ...

  4. mybatis 3.x 缓存Cache的使用

    mybatis 3.x 已经支持cache功能了,使用很简单,在mappper的xml文件里添加以下节点: <mapper namespace="com.cnblogs.yjmyzz. ...

  5. TinyFrame尾篇:整合Spring AOP实现用户认证

    创建Manager用户验证表 这一篇主要讲解使用AOP对用户操作进行验证,如果通过验证,则继续执行,反之,则不能执行.其思想和上一篇完全一致. 由于需要用到用户认证,所以我们新建一个Manager实体 ...

  6. Java实现生产者和消费者

    生产者和消费者问题是操作系统的经典问题,在实际工作中也常会用到,主要的难点在于协调生产者和消费者,因为生产者的个数和消费者的个数不确定,而生产者的生成速度与消费者的消费速度也不一样,同时还要实现生产者 ...

  7. mSites and Smarty

    目前的页面实现方式是需要向后台请求接口,返回 JSON 数据,动态拼接字符串塞进 DOM 中(innerHTML).考虑用 Smarty 生成静态页面,可以在后台用 PHP 得到数据,字符串拼接,然后 ...

  8. 反距离权重插值inverse distance weighting,IDW

    反距离权重 (IDW) 插值显式假设:彼此距离较近的事物要比彼此距离较远的事物更相似.当为任何未测量的位置预测值时,反距离权重法会采用预测位置周围的测量值.与距离预测位置较远的测量值相比,距离预测位置 ...

  9. 个人对final发布产品的排名

    结果 作品 组长 个人评委名次 个人评委平均 个人评委方差 投票数 团队评委名次 团队评委平均 团队评委方差 武志远-新蜂-俄罗斯 武志远 1 2.22 1.91 23 1 2 0.80 王森-天天向 ...

  10. 使用iframe标签结合springMvc做文件上传

    1.iframe.jsp <body> <h1>测试iframe文件上传</h1> <!-- 1.要求表单的target属性名称与iframe的name名字一 ...