[APIO2014]序列分割 --- 斜率优化DP
[APIO2014]序列分割
题目大意:
你正在玩一个关于长度为\(n\)的非负整数序列的游戏。这个游戏中你需要把序列分成\(k+1\)个非空的块。为了得到\(k+1\)块,你需要重复下面的操作\(k\)次:
选择一个有超过一个元素的块(初始时你只有一块,即整个序列)
选择两个相邻元素把这个块从中间分开,得到两个非空的块。
每次操作后你将获得那两个新产生的块的元素和的乘积的分数。你想要最大化最后的总得分。
\(n<=10^{5},k<=200\)
首先划分完\(k\)块后,发现非常像线性DP模型
自然地想,是不是分数跟划的顺序无关?
可以证明是的(归纳法)
那么,设
\(dp(i,j)\)表示枚举到了\(i\),第\(1...i\)切了几刀的最大收益。
有\(dp(i,j)=max(dp(k,j-1)+sum[k]*(sum[i]-sum[k]))(1<=k<=i-1)\)
那么展开式子,化为斜率优化的式子:
\(-dp(k,j-1)=sum[k]*sum[i]-sum[k]^{2}-dp(i,j)\)
其中\(k\)为\(sum[k]\),单调递增
其中\(x\)为\(sum[i]\),单调递增
要使\(dp(i,j)\)最大,因此维护下凸包,那么可以使用单调队列
空间滚一下就好
空间复杂度:\(O(n)\)(忽略记录决策点)
时间复杂度:\(O(nk)\)
注:被宏定义坑了很久。。。
#include<cstdio>
#include<cstring>
#define sid 100050
#define dd double
#define ll long long
#define ri register int
using namespace std; #define getchar() *S ++
char RR[], *S = RR;
inline int read(){
int p = , w = ;
char c = getchar();
while(c > '' || c < '') {
if(c == '-') w = -;
c = getchar();
}
while(c >= '' && c <= '') {
p = p * + c - '';
c = getchar();
}
return p * w;
} ll sum[sid], dp[][sid];
int lst[][sid], q[sid], n, k;
bool now = , pre = ; #define x(g) sum[(g)]
#define y(g) (sum[(g)]*sum[(g)]-dp[pre][(g)])
inline dd s(int i, int j) {
if(x(i) == x(j)) return -1e18;
return (dd)(y(i) - y(j)) / (dd)(x(i) - x(j));
} int main() {
fread(RR, , sizeof(RR), stdin);
n = read(); k = read();
for(ri i = ; i <= n; i ++) sum[i] = sum[i - ] + read();
for(ri j = ; j <= k; j ++) {
int fr = , to = ; now ^= ; pre ^= ;
for(ri i = ; i <= n; i ++) {
while(fr + <= to && s(q[fr], q[fr + ]) <= sum[i]) fr ++;
dp[now][i] = dp[pre][q[fr]] + sum[q[fr]] * (sum[i] - sum[q[fr]]);
lst[j][i]=q[fr];
while(fr + <= to && s(q[to - ], q[to]) >= s(q[to], i)) to --;
q[++ to] = i;
}
}
printf("%lld\n",dp[now][n]);
int e = n;
for(ri i = k; i >= ; i --) {
e = lst[i][e]; printf("%d ", e);
}
return ;
}
序列分割
[APIO2014]序列分割 --- 斜率优化DP的更多相关文章
- bzoj3675[Apio2014]序列分割 斜率优化dp
3675: [Apio2014]序列分割 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 3508 Solved: 1402[Submit][Stat ...
- 【bzoj3675】[Apio2014]序列分割 斜率优化dp
原文地址:http://www.cnblogs.com/GXZlegend/p/6835179.html 题目描述 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列 ...
- BZOJ 3675 [Apio2014]序列分割 (斜率优化DP)
洛谷传送门 题目大意:让你把序列切割k次,每次切割你能获得 这一整块两侧数字和的乘积 的分数,求最大的分数并输出切割方案 神题= = 搞了半天也没有想到切割顺序竟然和答案无关...我太弱了 证明很简单 ...
- BZOJ 3675 APIO2014 序列切割 斜率优化DP
题意:链接 方法:斜率优化DP 解析:这题BZ的数据我也是跪了,特意去网上找到当年的数据后面二十个最大的点都过了.就是过不了BZ. 看到这道题自己第一发DP是这么推得: 设f[i][j]是第j次分第i ...
- P3648 [APIO2014]序列分割 斜率优化
题解:斜率优化\(DP\) 提交:\(2\)次(特意没开\(long\ long\),然后就死了) 题解: 好的先把自己的式子推了出来: 朴素: 定义\(f[i][j]\)表示前\(i\)个数进行\( ...
- 【BZOJ3675】【APIO2014】序列分割 [斜率优化DP]
序列分割 Time Limit: 40 Sec Memory Limit: 128 MB[Submit][Status][Discuss] Description 小H最近迷上了一个分隔序列的游戏. ...
- BZOJ3675: [Apio2014]序列分割(斜率优化)
Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 4186 Solved: 1629[Submit][Status][Discuss] Descript ...
- BZOJ 3675: 序列分割 (斜率优化dp)
Description 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列分割成k+1个非空的子序列.为了得到k+1个子序列,小H需要重复k次以下的步骤: 1.小H首 ...
- BZOJ 3675: [Apio2014]序列分割( dp + 斜率优化 )
WA了一版... 切点确定的话, 顺序是不会影响结果的..所以可以dp dp(i, k) = max(dp(j, k-1) + (sumn - sumi) * (sumi - sumj)) 然后斜率优 ...
随机推荐
- R2—《R in Nutshell》 读书笔记(连载)
R in Nutshell 前言 例子(nutshell包) 本书中的例子包括在nutshell的R包中,使用数据,需加载nutshell包 install.packages("nutshe ...
- 【BZOJ】4316: 小C的独立集 静态仙人掌
[题意]给定仙人掌图,求最大独立集(选择最大的点集使得点间无连边).n<=50000,m<=60000. [算法]DFS处理仙人掌图 [题解]参考:[BZOJ]1023: [SHOI200 ...
- 【CodeForces】913 C. Party Lemonade
[题目]C. Party Lemonade [题意]给定n个物品,第i个物品重量为2^(i-1)价值为ci,每个物品可以无限取,求取总重量>=L的最小代价.1<=30<=n,1< ...
- HDU 2516 取石子游戏 (找规律)
题目链接 Problem Description 1堆石子有n个,两人轮流取.先取者第1次可以取任意多个,但不能全部取完.以后每次取的石子数不能超过上次取子数的2倍.取完者胜.先取者负输出" ...
- python作业Select版本FTP(第十周)
SELECT版FTP: 使用SELECT或SELECTORS模块实现并发简单版FTP 允许多用户并发上传下载文件 思路解析: 1. 使用IO多路复用的知识使用SELECTORS封装好的SELECTOR ...
- 2017 WebStorm 激活码 更新 Pycharm同样可用
[有效时间到2017 年 11月 23日] BIG3CLIK6F-eyJsaWNlbnNlSWQiOiJCSUczQ0xJSzZGIiwibGljZW5zZWVOYW1lIjoibGFuIHl1Iiw ...
- windows安装linux虚拟机、修改apt源
记录一下windows安装虚拟机以及初始配置的一些坑. 安装VMware Workstation 直接百度搜索VMware,选择合适的版本下载: 按照一般软件的安装步骤安装VMware Worksta ...
- C/C++——[05] 函数
函数是 C/C++语言中的一种程序组件单位.一个函数通常代表了一种数据处理的功能,由函数体和函数原型两部分组成.函数原型为这个数据处理功能指定一个标识符号(函数的名称).说明被处理数据的组成及其类型. ...
- ajax跨域的解决办法
<!DOCTYPE HTML> <html> <head> <meta http-equiv="content-type" content ...
- linux shell 一些命令
https://stackoverflow.com/questions/918886/how-do-i-split-a-string-on-a-delimiter-in-bash wc: https: ...