【洛谷3648/BZOJ3675】[APIO2014]序列分割(斜率优化DP)
题目:
注:这道题洛谷3648有SPJ,要求输出方案。BZOJ3675数据组数较多但不要求输出方案。
分析:
这可能是我第三次重学斜率优化了……好菜啊
这道题首先一看就是个DP。稍微推一推类似下面这种式子就会发现事实上结果和切的顺序无关
\]
那么就可以用\(f[i][j]\)表示切了\(j\)次,最右一次在\(i\)后面切的最大值。用\(sum[i]\)表示原序列前\(i\)个数之和,那么就有了这个DP方程(假设在\(i\)后面是第一次切割):
\]
其中\(j\)这一维可以滚动存储。转移的时候顺便记一下从什么地方转移过来就行。这个时间复杂度是\(O(n^2k)\)。丢一部分代码。
int work()
{
read(n), read(k);
for (int i = 1; i <= n; i++)
read(sum[i]), sum[i] += sum[i - 1];
for (int i = 2; i <= k; i++)
for (int j = n; j > 0; j--)
for (int g = 1; g < j; g++)
{
if (dp[j] < dp[g] + sum[g] * (sum[j] - sum[g]))
{
dp[j] = dp[g] + sum[g] * (sum[j] - sum[g]);
pre[i][j] = g;
}
}
int st = 0;
ll ans = 0;
for (int i = 1; i <= n; i++)
if (ans < dp[i] + sum[i] * (sum[n] - sum[i]))
{
ans = dp[i] + sum[i] * (sum[n] - sum[i]);
st = i;
}
write(ans), putchar('\n'), write(st);
for (int i = k; i > 1; i--)
putchar(' '), write(st = pre[i][st]);
return 0;
}
实测洛谷上有\(64\)分。64分够了,本文结束。
考虑斜率优化。以下的讨论均为在\(j\)(切的次数)固定的情况下,为方便说明,用\(f[i]\)表示\(f[i][j]\),\(g[i]\)表示\(f[i][j-1]\)。再来看这个式子。
\]
考虑对于\(g[j]\)和\(g[k](j<k<i)\),如果从\(g[j]\)转移到\(f[i]\)比从\(g[k]\)转移更优,那么一定满足:
\]
进行一些变换,得到:
\]
由于前缀和单调不降,\((-sum[j]+sum[k])\)是非负的,除到右边得到(暂时不考虑为\(-sum[j]+sum[k]=0\)的特殊情况):
\]
可以看出左侧的式子很“工整”。把\(g[j]-sum[j]^2\)看作点\(j\)的纵坐标,\(-sum[j]\)看作点\(j\)的横坐标,则左侧就是\(j\)和\(k\)两点之间的斜率。对于横坐标相等的两点,斜率根据纵坐标的符号视作正无穷或负无穷。
接下来阅读前,请时刻牢记:对于\(j<k<i\),如果\(j\)和\(k\)之间的斜率大于\(sum[i]\),则\(j\)比\(k\)优
同时还有这句话的反面:对于\(j<k<i\),如果\(j\)和\(k\)之间的斜率不大于\(sum[i]\),则\(j\)比\(k\)劣
由于\(sum[i]\)是单调不降的,所以满足决策单调性,即:如果对于\(f[i]\),从\(g[k]\)转移比从\(g[j]\)优\((j<k)\),则对于\(f[i'](i<i'\leq n)\),\(g[j]\)不可能是最优的(显然,\(j\)和\(k\)间的斜率是不受\(i\)影响的,而如果此时斜率已经小于等于\(sum[i]\)了,则以后也不可能大于\(sum[i]\),所以\(j\)以后永远不可能比\(k\)优) 。
那么可以维护一个斜率递增的单调队列。如果感到这部分难以理解,请再反复看上面三句加粗的话。当决策\(f[i]\)时,弹出单调队列首的若干元素,直到只剩一个元素或前两个元素的斜率大于\(sum[i]\)。当尝试插入\(i\)点时,弹出队尾的若干元素,直到只剩一个元素或队尾与\(i\)的斜率比队尾后两个元素大。在几何意义上,这是一个下凸包。读者可以画图理解。
代码:
#include <cstdio>
#include <algorithm>
#include <cctype>
#include <cstring>
using namespace std;
namespace zyt
{
template<typename T>
inline void read(T &x)
{
bool f = false;
char c;
x = 0;
do
c = getchar();
while (c != '-' && !isdigit(c));
if (c == '-')
f = true, c = getchar();
do
x = x * 10 + c - '0', c = getchar();
while (isdigit(c));
if (f)
x = -x;
}
template<typename T>
inline void write(T x)
{
static char buf[20];
char *pos = buf;
if (x < 0)
putchar('-'), x = -x;
do
*pos++ = x % 10 + '0';
while (x /= 10);
while (pos > buf)
putchar(*--pos);
}
typedef long long ll;
typedef long double ld;
const int N = 1e5 + 10, K = 210;
const ll LINF = 0x3f3f3f3f3f3f3f3fLL;
int n, k, now;
ll sum[N], dp[2][N];
int pre[K][N];
inline ll sq(const ll x)
{
return x * x;
}
inline ll y(const int i)
{
return dp[now ^ 1][i] - sq(sum[i]);
}
inline ll x(const int i)
{
return -sum[i];
}
inline ld ratio(const int i, const int j)
{
if (x(i) == x(j))
return (y(i) - y(j) > 0) ? LINF : -LINF;
else
return (ld)(y(i) - y(j)) / (x(i) - x(j));
}
int work()
{
static int q[N];
read(n), read(k);
for (int i = 1; i <= n; i++)
read(sum[i]), sum[i] += sum[i - 1];
for (int i = 2; i <= k; i++)
{
now = i & 1;
int h = 0, t = 1;
q[0] = 0;
for (int j = 1; j <= n; j++)
{
while (h + 1 < t && ratio(q[h], q[h + 1]) <= sum[j])
++h;
dp[now][j] = dp[now ^ 1][q[h]] + sum[q[h]] * (sum[j] - sum[q[h]]);
pre[i][j] = q[h];
while (h + 1 < t && ratio(q[t - 2], q[t - 1]) >= ratio(q[t - 1], j))
--t;
q[t++] = j;
}
}
int st = 0;
ll ans = 0;
for (int i = 1; i <= n; i++)
if (ans < dp[now][i] + sum[i] * (sum[n] - sum[i]))
{
ans = dp[now][i] + sum[i] * (sum[n] - sum[i]);
st = i;
}
write(ans), putchar('\n'), write(st);
for (int i = k; i > 1; i--)
putchar(' '), write(st = pre[i][st]);
return 0;
}
}
int main()
{
return zyt::work();
}
【洛谷3648/BZOJ3675】[APIO2014]序列分割(斜率优化DP)的更多相关文章
- bzoj3675[Apio2014]序列分割 斜率优化dp
3675: [Apio2014]序列分割 Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 3508 Solved: 1402[Submit][Stat ...
- 【洛谷3648】[APIO2014] 序列分割(斜率优化DP)
点此看题面 大致题意: 你可以对一个序列进行\(k\)次分割,每次得分为两个块元素和的乘积,求总得分的最大值. 区间\(DPor\)斜率优化\(DP\) 这题目第一眼看上去感觉很明显是区间\(DP\) ...
- 【bzoj3675】[Apio2014]序列分割 斜率优化dp
原文地址:http://www.cnblogs.com/GXZlegend/p/6835179.html 题目描述 小H最近迷上了一个分隔序列的游戏.在这个游戏里,小H需要将一个长度为n的非负整数序列 ...
- [APIO2014]序列分割 --- 斜率优化DP
[APIO2014]序列分割 题目大意: 你正在玩一个关于长度为\(n\)的非负整数序列的游戏.这个游戏中你需要把序列分成\(k+1\)个非空的块.为了得到\(k+1\)块,你需要重复下面的操作\(k ...
- BZOJ3675: [Apio2014]序列分割(斜率优化)
Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 4186 Solved: 1629[Submit][Status][Discuss] Descript ...
- BZOJ 3675 [Apio2014]序列分割 (斜率优化DP)
洛谷传送门 题目大意:让你把序列切割k次,每次切割你能获得 这一整块两侧数字和的乘积 的分数,求最大的分数并输出切割方案 神题= = 搞了半天也没有想到切割顺序竟然和答案无关...我太弱了 证明很简单 ...
- 洛谷 P4093 [HEOI2016/TJOI2016]序列 CDQ分治优化DP
洛谷 P4093 [HEOI2016/TJOI2016]序列 CDQ分治优化DP 题目描述 佳媛姐姐过生日的时候,她的小伙伴从某宝上买了一个有趣的玩具送给他. 玩具上有一个数列,数列中某些项的值可能会 ...
- P3648 [APIO2014]序列分割 斜率优化
题解:斜率优化\(DP\) 提交:\(2\)次(特意没开\(long\ long\),然后就死了) 题解: 好的先把自己的式子推了出来: 朴素: 定义\(f[i][j]\)表示前\(i\)个数进行\( ...
- BZOJ 3675 APIO2014 序列切割 斜率优化DP
题意:链接 方法:斜率优化DP 解析:这题BZ的数据我也是跪了,特意去网上找到当年的数据后面二十个最大的点都过了.就是过不了BZ. 看到这道题自己第一发DP是这么推得: 设f[i][j]是第j次分第i ...
- 【洛谷 P3648】 [APIO2014]序列分割 (斜率优化)
题目链接 假设有\(3\)段\(a,b,c\) 先切\(ab\)和先切\(bc\)的价值分别为 \(a(b+c)+bc=ab+bc+ac\) \((a+b)c+ab=ab+bc+ac\) 归纳一下可以 ...
随机推荐
- python文件读写及形式转化和CGI的简单应用
一丶python文件读写学习笔记 open() 将会返回一个 file 对象,基本语法格式如下: open(filename, mode) filename:包含了你要访问的文件名称的字符串值. mo ...
- led1,1s取反,led2计数10次取反
1 //利用定时器0 1s,led1取反,利用计数器1,跳10,取反 #include<reg52.h> #define uchar unsigned char #define uint ...
- 洛谷 2173 BZOJ 2816 [ZJOI2012]网络
[题解] 明显的LCT模板题,c种颜色就开c棵LCT好了.. #include<cstdio> #include<algorithm> #define N 100010 #de ...
- FJoi2017 1月21日模拟赛 comparison(平衡树+thita重构)
题目大意: 经黄学长指出,此题原题出自2014湖北省队互测 没有人的算术 规定集合由二元组(A,B)构成,A.B同时也是两个这样的集合,即A.B本身也是二元组 规定二元组S为严格最小集合,S=(S,S ...
- eclipse如何能快速找到某个文件夹或者文件
eclipse如何能快速找到某个文件夹或者文件 直接在editor中右键 Show in -> Package Explorer 在package explore 中选中link就可以了 (魔芋 ...
- 矩形面积求并(codevs 3044)
题目描述 Description 输入n个矩形,求他们总共占地面积(也就是求一下面积的并) 输入描述 Input Description 可能有多组数据,读到n=0为止(不超过15组) 每组数据第一行 ...
- oracle中的类似BIN$MrkCYT9eTTK+0sStMwn7+Q==$0的表的作用
https://www.2cto.com/database/201211/166482.html https://docs.oracle.com/cd/E11882_01/server.112/e40 ...
- [bzoj2038][2009国家集训队]小Z的袜子(hose)_莫队
小Z的袜子 hose 2009-国家集训队 bzoj-2038 题目大意:给定一个n个袜子的序列,每个袜子有一个颜色.m次询问:每次询问一段区间中每种颜色袜子个数的平方和. 注释:$1\le n,m\ ...
- cogs——908. 校园网
908. 校园网 ★★ 输入文件:schlnet.in 输出文件:schlnet.out 简单对比 时间限制:1 s 内存限制:128 MB USACO/schlnet(译 by Fe ...
- Json解析工具Jackson(使用注解)--jackson框架自定义的一些json解析注解
Json解析工具Jackson(使用注解)--jackson框架自定义的一些json解析注解 @JsonIgnoreProperties 此注解是类注解,作用是json序列化时将Javabean中的一 ...