【BZOJ-3675】序列分割 DP + 斜率优化
3675: [Apio2014]序列分割
Time Limit: 40 Sec Memory Limit: 128 MB
Submit: 1420 Solved: 583
[Submit][Status][Discuss]
Description
Input
输入第一行包含两个整数n,k(k+1≤n)。
Output
输出第一行包含一个整数,为小H可以得到的最大分数。
Sample Input
4 1 3 4 0 2 3
Sample Output
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 + 斜率优化的更多相关文章
- BZOJ 3675: [Apio2014]序列分割( dp + 斜率优化 )
WA了一版... 切点确定的话, 顺序是不会影响结果的..所以可以dp dp(i, k) = max(dp(j, k-1) + (sumn - sumi) * (sumi - sumj)) 然后斜率优 ...
- 【BZOJ3675】序列分割(斜率优化,动态规划)
[BZOJ3675]序列分割(斜率优化,动态规划) 题面 Description 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列.为了得 ...
- BZOJ_3675_[Apio2014]序列分割_斜率优化
BZOJ_3675_[Apio2014]序列分割_斜率优化 Description 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列.为了 ...
- BZOJ 3675 [Apio2014]序列分割 (斜率优化DP)
题目链接 BZOJ 3675 首先最后的答案和分割的顺序是无关的, 那么就可以考虑DP了. 设$f[i][j]$为做了$i$次分割,考虑前$j$个数之后的最优答案. 那么$f[i][j] = max( ...
- BZOJ 3675: 序列分割 (斜率优化dp)
Description 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列.为了得到k+1个子序列,小H需要重复k次以下的步骤: 1.小H首 ...
- bzoj 3675: [Apio2014]序列分割【斜率优化dp】
首先看这个得分方式,容易发现就相当于分k段,每段的值和两两乘起来. 这样就很容易列出dp方程:设f[i][j]为到j分成分成i段,转移是 \[ f[i][j]=max { f[k][j]+s[k]*( ...
- 【洛谷3648】[APIO2014] 序列分割(斜率优化DP)
点此看题面 大致题意: 你可以对一个序列进行\(k\)次分割,每次得分为两个块元素和的乘积,求总得分的最大值. 区间\(DPor\)斜率优化\(DP\) 这题目第一眼看上去感觉很明显是区间\(DP\) ...
- P3648 [APIO2014]序列分割(斜率优化dp)
P3648 [APIO2014]序列分割 我们先证明,分块的顺序对结果没有影响. 我们有一个长度为3的序列$abc$ 现在我们将$a,b,c$分开来 随意枚举一种分块方法,如$(ab)(c)$,$(a ...
- 2018.09.29 bzoj3675: [Apio2014]序列分割(斜率优化dp)
传送门 斜率优化dp经典题目. 首先需要证明只要选择的K个断点是相同的,那么得到的答案也是相同的. 根据分治的思想,我们只需要证明有两个断点时成立,就能推出K个断点时成立. 我们设两个断点分成的三段连 ...
随机推荐
- delphi附带通用控件安装方法:
附带通用控件安装方法:----------基本安装1.对于单个控件,Componet-->install component..-->PAS或DCU文件-->install;2.对于 ...
- 微软职位内部推荐-Senior Software Engineer_Azure
微软近期Open的职位: Job Title: Senior Software Engineer Location: Shanghai, China Have you ever imagined th ...
- CSS background-position 问题
今天在用background-position进行BODY背景图定位的时候发现100% 100%理应定位在右下角,结果却不一致,查了下语法也没问题 结果发现是background-attachment ...
- 实现Linux与Windows下一致的命令行
这其实是个非常简单的东西. 我们会写一些命令行的工具,一般跨平台的话,会用python或者perl写,比如叫foo.py,然后在Windows和Linux下调用这个脚本: Linux: foo.py ...
- 博客搬家。新博客地址 http://fangjian0423.github.io/
以后新的博客会发到 http://fangjian0423.github.io/ 里. 这里基本上不会再更新博客了.
- .clear 万能清除浮动
html body div.clear, html body span.clear { background: none; border: 0; clear: both; display: block ...
- 求解区间最值 - RMQ - ST 算法介绍
解析 ST 算法是 RMQ(Range Minimum/Maximum Query)中一个很经典的算法,它天生用来求得一个区间的最值,但却不能维护最值,也就是说,过程中不能改变区间中的某个元素的值.O ...
- hibernate Expression详解
关键字: hibernate expression hibernate Expression详解Expression.gt:对应SQL条件中的"field > value " ...
- DevExpress中设置PanelControl背景的方法
首先当然是设置BackColor的颜色,但是设置完之后往往是没有反映的,这就Dev的好处带来的不好,然后我们需要自己定义两个属性 1.设置LookAndFeel下的style为Flat或UtralFl ...
- jquery的getjson与jsonp
仔细的学习jquery的getjson的用法. http://www.cnblogs.com/leejersey/p/3750232.html http://www.jb51.net/article/ ...