CF1175G
叉姐牛逼。
\(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的更多相关文章
随机推荐
- java实现责任链模式的小demo
//一个请假请求 public class LeaveRequest { private int leaveDays; private String name; public void leave() ...
- 小白自制Linux开发板 八. Linux音频驱动配置
不知不觉小白自制开发板系列已经到第八篇了,本篇要配置的是音频驱动,也算是硬件部分的最后一片了,积攒的文章也差不多全放完了,后续更新可能会放缓,还请见谅. 对于F1C200s是自带了多媒体处理功能的,所 ...
- JVM:Java中的引用
JVM:Java中的引用 本笔记是根据bilibili上 尚硅谷 的课程 Java大厂面试题第二季 而做的笔记 在原来的时候,我们谈到一个类的实例化 Person p = new Person() 在 ...
- 单片机stm32串口分析
stm32作为现在嵌入式物联网单片机行业中经常要用多的技术,相信大家都有所接触,今天这篇就给大家详细的分析下有关于stm32的出口,还不是很清楚的朋友要注意看看了哦,在最后还会为大家分享有些关于stm ...
- 常用JAVA API :String 、StringBuilder、StringBuffer的常用方法和区别
摘要 本文将介绍String.StringBuilder类的常用方法. 在java中String类不可变的,创建一个String对象后不能更改它的值.所以如果需要对原字符串进行一些改动操作,就需要用S ...
- Python课程笔记(一)
由于新冠状病毒的爆发,不得不在家里上网课,开课已经两个礼拜了,今天上完Python课后,准备整理一下最近学习Python的笔记. 人生苦短,我用Python 一.Hello World 初学一门新的语 ...
- 使用 ASP.NET Core 3.1 的微服务开发指南
使用 ASP.NET Core 3.1 的微服务 – 终极详细指南 https://procodeguide.com/programming/microservices-asp-net-core/ A ...
- C# 如何将日期格式化ISO8601模式
类似于这样的时间戳格式:预计来访时间,时间参数需满足ISO8601格式:yyyy-MM-ddTHH:mm:ss+当前时区,例如北京时间:2018-07-26T15:00:00 + 08:00 stri ...
- JAVA笔记2__类/封闭性/构造方法/方法的重载/匿名对象
public class Main { public static void main(String[] args) { Chicken c1 = new Chicken(); Chicken c2 ...
- 恶意代码の奇客pdf分析
目录 恶意代码の奇客pdf分析 奇客PDF安装包分析 静态分析基础技术 上传杀毒网 查壳 编译时间 导入表分析 资源查看 动态分析基础技术 Process Monitor监控 Process Expl ...