叉姐牛逼。

\(f_{k,i} = \min_{0\leq j <i}{f_{k - 1,j} + RMQ(j + 1,i) * (i - j)}\)

我们考虑在序列上分治一波。

按照\(m\)切开,\(i >= m\),

我们需要找到

\(\min_{0\leq j < m} f_{k - 1,j} + \max{(suf[j],pre[i])} * (i - j)\)

然后我们发现此时\(suf[j]\)具有单调性。

我们可以分类讨论一下。

\(suf_j \leq pre_i\)

我们需要找到

\(\min_j g_j - pre[i] * j\)

否则

我们需要找到

\(min_j(g_j - suf_j * j) + i _suf[j]\)

考虑分治加单调栈处理。

叉姐牛逼。

#include<iostream>
#include<cstdio>
#include<algorithm>
#define N 20001
#define INF 400000005 struct Line{
int k,b;
int val(int x){return k * x + b;}
}; inline bool check(Line u,Line v,Line w){
return 1ll * (v.b - u.b) * (v.k - w.k) < 1ll * (w.b - v.b) * (u.k - v.k);
} inline void qmin(int &x,int a){x = (x > a) ? a : x;} int n,a[N],dp[2][N],suf[N],pre[N];
Line stack[N]; #define m ((l + r) >> 1) inline void work(int *pdp,int *dp,int l,int r){
if(l < r){
suf[m] = 0;
for (int i = m; i > l; --i) {
suf[i - 1] = std::max(a[i], suf[i]);
}
pre[m] = 0;
for (int i = m + 1; i <= r; ++i) {
pre[i] = std::max(pre[i - 1], a[i]);
}
for (int i = m + 1, bot = n, j = m; i <= r; ++i) {
while (j >= l && suf[j] <= pre[i]) {
const Line line{-j, pdp[j]};
while (bot + 1 < n && !check(line, stack[bot], stack[bot + 1])) {
bot++;
}
stack[--bot] = line;
j--;
}
int x = pre[i];
while (bot + 1 < n && stack[bot].val(x) > stack[bot + 1].val(x)) {
bot++;
}
qmin(dp[i], stack[bot].val(x) + i * pre[i]);
}
for (int i = r, top = -1, j = l; i > m; --i) {
while (j <= m && suf[j] >= pre[i]) {
Line line{suf[j], pdp[j] - j * suf[j]};
j++;
while (j <= m && suf[j] == line.k) {
line.b = std::min(line.b, pdp[j] - j * suf[j]);
j++;
}
while (top - 1 >= 0 && !check(stack[top - 1], stack[top], line)) {
top--;
}
stack[++top] = line;
}
int x = i;
while (top - 1 >= 0 && stack[top - 1].val(x) < stack[top].val(x)) {
top--;
}
if (~top) {
qmin(dp[i], stack[top].val(x));
}
}
work(pdp, dp, l, m);
work(pdp, dp, m + 1, r);
}
} int main() {
int M;
scanf("%d%d", &n, &M);
for (int i = 1; i <= n; ++i) {
scanf("%d", a + i);
}
dp[0][0] = 0;
std::fill(dp[0] + 1, dp[0] + n + 1, INF);
for (int j = 0; j < M; ++j) {
std::fill(dp[(j + 1) & 1], dp[(j + 1) & 1] + (n + 1), INF);
work(dp[j & 1], dp[(j + 1) & 1], 0, n);
}
printf("%d\n", dp[M & 1][n]);
}

CF1175G的更多相关文章

随机推荐

  1. Setoolkit部署

    禁止使用本文的知识进行违法犯罪活动!!学习这些内容是为了更好的防范钓鱼网站 详见我的github仓库 Setoolkit : Social-Engineer Toolkit(社会工程学工具包) 其作为 ...

  2. Web前端安全之安全编码原则

    随着Web和移动应用等的快速发展,越来越多的Web安全问题逐渐显示出来.一个网站或一个移动应用,如果没有做好相关的安全防范工作,不仅会造成用户信息.服务器或数据库信息的泄露,更可能会造成用户财产的损失 ...

  3. 深入理解java中main方法

    理解main方法语法 深入理解main方法: 解释main方法的形式:public static void main(String[] args){} main方法调用者:虚拟机 java虚拟机需要调 ...

  4. SpringBoot 01 hello world 01

    hello world项目结构: pom中配置的依赖相当于spring boot的可安装插件,需要下载的依赖直接在里边配置. 目前用到的每个注解: 1.主程序中 @SpringBootApplicat ...

  5. JVM:内存模型

    JVM:内存模型 说明:这是看了 bilibili 上 黑马程序员 的课程 JVM完整教程 后做的笔记 1. java 内存模型 很多人将[java 内存结构]与[java 内存模型]傻傻分不清,[j ...

  6. Alpha项目展示

    项目 内容 这个作业属于哪个课程 2021春季软件工程(罗杰 任健) 这个作业的要求在哪里 Alpha-项目展示 我们是谁 删库跑路对不队 我们在做什么 题士 进度如何 进度总览 一.项目与团队亮点 ...

  7. (六)、Docker 之 Dockerfile

    1.什么是Dockerfile Dockerfile是用来构建Docker镜像的构建文件,是由一系列命令和参数构成的脚本. 2.Dockerfile解析过程 前提认知: 每条保留字指令都必须为大写字母 ...

  8. AOP源码解析:AspectJAwareAdvisorAutoProxyCreator类的介绍

    AspectJAwareAdvisorAutoProxyCreator 的类图 上图中一些 类/接口 的介绍: AspectJAwareAdvisorAutoProxyCreator : 公开了Asp ...

  9. 力扣 - 剑指 Offer 57 - II. 和为s的连续正数序列

    题目 剑指 Offer 57 - II. 和为s的连续正数序列 思路1(双指针/滑动窗口) 所谓滑动窗口,就是需要我们从一个序列中找到某些连续的子序列,我们可以使用两个for循环来遍历查找,但是未免效 ...

  10. Python | 实现pdf文件分页

    不知道大家有没有遇到过这么一种情况,就比如一个pdf格式的电子书,我们经常浏览的是其中的一部分,而这电子书的页数很大,每当需要浏览时,就需要翻到对应的页码,就有点儿繁琐. 还有一些情况,比如,我们想分 ...