[APIO2014]序列分割
嘟嘟嘟
复习一下斜率优化,感觉已经忘得差不多了……
这题切入点在与答案跟切的顺序无关。
证明就是假如有三段权值分别为\(x, y, z\),那么这两刀不管按什么顺序切,得到的结果都是\(xy + xz + yz\)。
然后就可以dp。
令\(dp[i][j]\)表示前\(i\)个数切\(j\)刀的最大得分,于是就有\(dp[i][j] = max\{ dp[k][j - 1] + s[k] * (s[i] - s[k]) \}\)。
观察这个式子,发现\(j\)只能从\(j - 1\)转移过来,那索性把\(j\)换到第一维,然后就可以滚动数组省去第一维了,即\(f[i] = max \{ g[k] + s[k] * (s[i] - s[k]) \}\)。
看到乘积,似乎能想到斜率优化。于是假设\(t_2 > t_1\),且\(t_2\)的决策比\(t_1\)优,这时候\(t_1\)就可以扔掉了。那么就有
g[t_2] + s[t_2] * (s[i] - s[t_2]) &\geqslant g[t_1] + s[t_1] * (s[i] - s[t_1]) \\
\frac{(g[t_1] - s[t_1] ^ 2) - (g[t_2] - s[t_2] ^ 2)}{g[t_2] - g[t_1]} &\leqslant s[i]
\end{align*}\]
于是我们用单调队列维护一个下凸壳就好啦。
坑点在于\(s[t_1] = s[t_2]\),这时候斜率直接返回\(-INF\),把\(t_1\)扔出去。
彩蛋:某谷第12个点卡精度,然后我发现乘以\(1.0\)比强制类型转换成double精度要高……
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const ll INF = 1e18;
const db eps = 1e-8;
const int maxn = 2e5 + 5;
const int maxm = 205;
inline ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) last = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
}
int n, K;
ll a[maxn];
ll sum[maxn], f[maxn], g[maxn];
int q[maxn], pre[maxn][maxm];
In db slope(int i, int j)
{
if(sum[i] == sum[j]) return -INF;
return 1.0 * ((g[i] - sum[i] * sum[i]) - (g[j] - sum[j] * sum[j])) / ((db)sum[j] - sum[i]);
}
int main()
{
n = read(), K = read();
for(int i = 1; i <= n; ++i) a[i] = read(), sum[i] = sum[i - 1] + a[i];
for(int j = 1; j <= K; ++j)
{
int l = 1, r = 0;
q[++r] = 0;
for(int i = 1; i <= n; ++i)
{
while(l < r && slope(q[l], q[l + 1]) <= sum[i]) ++l;
f[i] = g[q[l]] + sum[q[l]] * (sum[i] - sum[q[l]]);
pre[i][j] = q[l];
while(l < r && slope(q[r - 1], q[r]) >= slope(q[r], i)) --r;
q[++r] = i;
}
memcpy(g, f, sizeof(f));
}
write(f[n]), enter;
for(int j = n, i = K; i; --i) j = pre[j][i], write(j), space; enter;
return 0;
}
[APIO2014]序列分割的更多相关文章
- 【斜率DP】BZOJ 3675:[Apio2014]序列分割
3675: [Apio2014]序列分割 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 1066 Solved: 427[Submit][Statu ...
- BZOJ 3675: [Apio2014]序列分割( dp + 斜率优化 )
WA了一版... 切点确定的话, 顺序是不会影响结果的..所以可以dp dp(i, k) = max(dp(j, k-1) + (sumn - sumi) * (sumi - sumj)) 然后斜率优 ...
- bzoj3675[Apio2014]序列分割 斜率优化dp
3675: [Apio2014]序列分割 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 3508 Solved: 1402[Submit][Stat ...
- BZOJ_3675_[Apio2014]序列分割_斜率优化
BZOJ_3675_[Apio2014]序列分割_斜率优化 Description 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列.为了 ...
- 斜率优化入门学习+总结 Apio2011特别行动队&Apio2014序列分割&HZOI2008玩具装箱&ZJOI2007仓库建设&小P的牧场&防御准备&Sdoi2016征途
斜率优化: 额...这是篇7个题的题解... 首先说说斜率优化是个啥,额... f[i]=min(f[j]+xxxx(i,j)) ; 1<=j<i (O(n^2)暴力)这样一个式子,首 ...
- P3648 [APIO2014]序列分割(斜率优化dp)
P3648 [APIO2014]序列分割 我们先证明,分块的顺序对结果没有影响. 我们有一个长度为3的序列$abc$ 现在我们将$a,b,c$分开来 随意枚举一种分块方法,如$(ab)(c)$,$(a ...
- [luogu P3648] [APIO2014]序列分割
[luogu P3648] [APIO2014]序列分割 题目描述 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列.为了得到k+1个子序 ...
- 洛谷 P3648 [APIO2014]序列分割 解题报告
P3648 [APIO2014]序列分割 题目描述 你正在玩一个关于长度为\(n\)的非负整数序列的游戏.这个游戏中你需要把序列分成\(k+1\)个非空的块.为了得到\(k+1\)块,你需要重复下面的 ...
- [APIO2014]序列分割 --- 斜率优化DP
[APIO2014]序列分割 题目大意: 你正在玩一个关于长度为\(n\)的非负整数序列的游戏.这个游戏中你需要把序列分成\(k+1\)个非空的块.为了得到\(k+1\)块,你需要重复下面的操作\(k ...
- BZOJ3675 [Apio2014]序列分割 【斜率优化dp】
3675: [Apio2014]序列分割 Time Limit: 40 Sec Memory Limit: 128 MB Submit: 3366 Solved: 1355 [Submit][St ...
随机推荐
- 什么是LogDashboard?
What is LogDashboard 接上篇 LogDashboard是可视化的日志面板,摆脱了传统查看txt与数据库的方式. 使查看日志变的简单方便并且可供分析 基于Net Core中间件编写适 ...
- Servlet+Tomcat总结
Tomcat的缺省端口是多少,怎么修改 1.找到Tomcat目录下的conf文件夹 2.进入conf文件夹里面找到server.xml文件 3.打开server.xml文件 4.在server.xml ...
- 用Scrutor来简化ASP.NET Core的DI注册
目录 背景 Scrutor简介 Scrutor的简单使用 注册接口的实现类 注册类自身 重复注册处理策略 总结 相关文章 背景 在我们编写ASP.NET Core代码的时候,总是离不开依赖注入这东西. ...
- [二十四]JavaIO之PrintWriter
功能简介 PrintWriter 向文本输出流打印对象的格式化表示形式 他与PrintStream的逻辑上功能目的是相同的--他们都想做同一件事情--更便捷的格式化打印输出 Print ...
- [十五]java.math包简介,RoundingMode与MathContext
java.math包提供了java中的数学类 包括基本的浮点库.复杂运算以及任意精度的数据运算 '可以看得到,主要包括三个类一个枚举 BigDecimal和BigInteger接下来会详细介绍 先 ...
- WPF 可触摸移动的ScrollViewer控件
ListBox支持触摸滑动,而ScrollViewer默认不支持.需要设置PanningMode属性,如果不设置PanningMode,如何自定义触摸滑动? ScrollViewer如需要添加上下/左 ...
- Go中变量作用域的小坑
直接上一实例: package main import "fmt" func main(){ fmt.Println("for start") ; a < ...
- 学JAVA第十一天,属性与方法
今天清明节假期结束第二天,昨天请了一天假去考科目二,还好考过了,O(∩_∩)O哈哈~~~~ 今天老师讲了类的属性与方法的使用 就用代码来说明吧: package pkg3;public class T ...
- 【学习笔记】tensorflow图片读取
目录 图像基本概念 图像基本操作 图像基本操作API 图像读取API 狗图片读取 CIFAR-10二进制数据读取 TFRecords TFRecords存储 TFRecords读取方法 图像基本概念 ...
- FrameSet定义页面宽度并且居中
frameset定义一个1000px的页面并且居中 <frame src = "about:blank"></frame> : 这个语句的功能是在一个框架里 ...