【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个断点时成立. 我们设两个断点分成的三段连 ...
随机推荐
- PAT 1029. 旧键盘(20)
旧键盘上坏了几个键,于是在敲一段文字的时候,对应的字符就不会出现.现在给出应该输入的一段文字.以及实际被输入的文字,请你列出肯定坏掉的那些键. 输入格式: 输入在2行中分别给出应该输入的文字.以及实际 ...
- DEDECMS之三 首页、列表页怎么调用文章内容
一.首页调用 百度了很多,没有找到实际的解决方法,对于直接读取数据库,这种写法不会采取. 后来,仔细考虑,这部分解决的内容不会很多,所以直接使用了简介的内容 方法一(默认长度55) [field:in ...
- 【分布式协调器】Paxos的工程实现-cocklebur简介(二)
Cocklebur集群的工作原理 在集群正常工作时,整个集群只会有一个Leader,其他都是Follower.Client可以注册到某个Follower,当然也可以注册到Leader,为了减轻Lead ...
- php缓存技术(减少数据库服务器压力)
静态缓存(保存在磁盘上的静态文件,用PHP生成数据放入静态文件中) a) php操作缓存 i. 生成缓存 ii. 获取缓存 iii. 删除缓存 判断目录是否存在:is_dir() dirname ...
- Bootstrap系列 -- 13. 内联表单
有时候我们需要将表单的控件都在一行内显示.在Bootstrap框架中实现这样的表单效果是轻而易举的,你只需要在<form>元素中添加类名“form-inline”即可 如果你要在input ...
- 系统升级日记(1)- 升级到SQL Server 2012
最近一段时间在公司忙于将各类系统进行升级,其最主要的目标有两个,一个是将TFS2010升级到TFS2013,另外一个是将SharePoint 2010升级到SharePoint 2013.本记录旨在记 ...
- 构造函数的return返回值
3 1. 2. 3.
- java的HashCode方法
总的来说,Java中的集合(Collection)有两类,一类是List,再有一类是Set. 前者集合内的元素是有序的,元素可以重复: 后者元素无序,但元素不可重复. 要想保证元素不重复,可两个元素是 ...
- 转一篇Unity客户端与Java服务器的通信
转自:http://www.programering.com/a/MTNxYDMwATQ.html A few days ago a friend asked me about Unity3D ins ...
- 前端框架——BootStrap学习
BootStrap简单总结下:1.栅格系统,能够很好的同时适应手机端和PC端(及传说中的响应式布局) 2.兼容性好 接下来是对BootStrap学习的一些基础案例总结和回顾: 首先引入:bootstr ...