很显然有一个暴力 \(dp\),令 \(dp_{i, j}\) 表示最后一次划分在 \(i\) 上次划分在 \(j\) 的最小花费,令 \(S_i = \sum\limits_{j = 1} ^ i a_j\)。那么有转移:

\[dp_{i, j} = \min\{dp_{j, k} + (S_i - S_j) ^ 2\}(S_i - S_j \ge S_j - S_k)
\]

可以发现 \(dp_{j, k}\) 的值是和 \(i\) 无关的,只是 \(k\) 的取值范围和 \(i\) 有关,那么我们只需要知道 \(k\) 的取值范围再取这个范围内的最小值即可。将后面那个条件移项可得 \(S_k \ge 2 \times S_j - S_i\),因此 \(k\) 的取值范围应该在 \(2 \times S_j - S_i \sim j - 1\),而当 \(j\) 固定时,因为 \(S_i\) 随着 \(i\) 的增大单调递增,所以 \(k\) 能取到的下界不断减小,于是我们可以考虑在 \(i\) 的同时维护每个 \(j\) 的下界以及当前能取到的最小 \(dp_{j, k}\) 这样均摊复杂度就是 \(O(n ^ 2)\) 的了。

rep(i, 1, n) dp[i][0] = sum[i] * sum[i], p[i] = i - 1, mx[i] = inf;
rep(i, 2, n){
rep(j, 1, i - 1){
while(p[j] >= 0 && sum[p[j]] >= 2 * sum[j] - sum[i]) mx[j] = min(mx[j], dp[j][p[j]]), --p[j];
if(p[j] < j - 1) ++p[j];
if(mx[j] != inf) dp[i][j] = mx[j] + (sum[i] - sum[j]) * (sum[i] - sum[j]);
}
}
rep(i, 0, n - 1) ans = min(ans, dp[n][i]);
printf("%lld", ans);
return 0;

如果这个 \(dp\) 不能压缩状态是显然无法优化的,但为了保证题目中的条件,我们根本无法压缩状态,下面一个常见的手段就是可以打个决策转移的表。可以发现我们每次转移 \(j \rightarrow i\) 都是选择了一个最大的能满足条件的 \(k\) 从 \(dp_{j, k} \rightarrow dp_{i, j}\),并且可以发现当 \(j\) 越大时 \(dp_{i, j}\) 越大。这样换句话来说就是每次我们让最后一段尽可能选择小的是更优的,实际上因为我们有 \((a + b) ^ 2 > a ^ 2 + b ^ 2\) 因此我们要尽可能多分段,如果我们每次选择最小的一段,不仅能够分更多的段,并且还能让后面尽可能分的段更多,并且能让当前的贡献更小,所以这样做一定是更优的。针对这个贪心,我们可以令 \(dp_i\) 表示当前划分到以 \(i\) 结尾的段的最小花费,令 \(p_i\) 表示 \(i\) 是由哪里转移来的,那么每次转移就要找到一个最大 \(j\) 满足 \(S_i - S_j \ge S_j - S_{p_j}\) 移项可得 \(S_i \ge 2 \times S_j - S_{p_j}\),我们大可以使用线段树二分出左边第一个比某个数大的位置,但实际上这里还有个 \(O(n)\) 做法。可以发现因为 \(S_i\) 是单调递增的,因此我们之前能够选择的 \(j\) 随着 \(i\) 的增大一定是还能继续选的。因此我们可以维护一个类似单调队列的东西,在队列中 \(2 \times S_j - S_{p_j}\) 单调递增,每次我新加入一个元素,从队尾一直开始弹出知道这个 \(2 \times S_{q_t} - S_{p_{q_t}} < 2 \times S_j - S_{p_j}\) 为止,那么这样我们获得的每个值的位置都将是当前最靠右的点,并且由于 \(S_i\) 在不断单调递增,我们只需要每次不断移动队尾找到队列中最后一个 \(\le S_i\) 的元素即可。

dp[1] = a[1] * a[1], h = 1, t = 2, q[1] = 0, q[2] = 1;
rep(i, 2, n){
while(h <= t && 2 * sum[q[h]] - sum[p[q[h]]] <= sum[i]) ++h;
--h, p[i] = q[h];
dp[i] = dp[p[i]] + (sum[i] - sum[p[i]]) * (sum[i] - sum[p[i]]);
while(h <= t && 2 * sum[i] - sum[p[i]] <= 2 * sum[q[t]] - sum[p[q[t]]]) --t;
q[++t] = i;
}
printf("%lld", dp[n]);

最后那 \(12\) 分需要使用高精度,根据我们的流程可以看出实际上我们不需要记录 \(dp\) 数组,只需要记录之前的 \(p\) 即可,最后我们只需要不断往下迭代加上每一段的值即可,我的高精太丑了(其实是写的 \(\_\_int128\))就不贴了。

CSP2019 Day2T2 划分的更多相关文章

  1. CSP2019 D2T2 划分 (单调队列DP)

    题目 洛谷传送门 题解 就是这道题搞我退役考场上写了n^2 64分,结果爆成8-12分.直接GG. 考场上想到正解的写法被自己否决了 题解传送门(看到这道送我退役的题目⑧太想写题解) 六行O(n2)O ...

  2. 【CSP2019】题解合集

    诈个尸 先挖坑 虽然连去都没去但还是想做做 今年貌似比去年还毒瘤啊... yrx.hjw都进了省队线tql orz (myh:没AK真丢脸 Day1T1 格雷码 Day1T2 括号树 Day1T3 树 ...

  3. CSP-S 2019 Solution

    Day1-T1 格雷码(code) 格雷码是一种特殊的 \(n\) 位二进制串排列法,要求相邻的两个二进制串恰好有一位不同,环状相邻. 生成方法: \(1\) 位格雷码由两个 \(1\) 位的二进制串 ...

  4. CSP2019 S2滚粗记

    最好分数:100+20+10+64+64+55 最坏分数:100+20+10+64+36+55 咕咕数据分数:100+25+10+64+60+55 CCF官方: 100+35+10+64+36+55= ...

  5. CSP2019题解

    CSP2019题解 格雷码 按照生成的规则模拟一下即可. 代码 括号树 看到括号匹配首先想到用栈,然后又在树上就可以想到可追溯化栈. 令\(a_i=1\)表示\(i\)号节点上的括号为(,否则为), ...

  6. CSP2019 题解

    CSP2019 题解 D1T1 格雷码(code) 题目传送门 https://loj.ac/problem/3208 题解 按照题意模拟就可以了. 对于第 \(i\) 位,如果 \(k \geq 2 ...

  7. [LeetCode] Partition List 划分链表

    Given a linked list and a value x, partition it such that all nodes less than x come before nodes gr ...

  8. SWMM模型子汇水区划分的几种方法

    子汇水区的划分是SWMM模型建模的主要步骤之一,划分的好坏对结果精度有比较大的影响.概括来讲,子汇水区的划分有以下几种思路: (1)根据管网走向.建筑物和街道分布,直接人工划分子汇水区.这个方法适用于 ...

  9. 等价类划分方法的应用(jsp)

    [问题描述] 在三个文本框中输入字符串,要求均为1到6个英文字符或数字,按submit提交. [划分等价类] 条件1: 字符合法; 条件2: 输入1长度合法; 条件3: 输入2长度合法: 条件4: 输 ...

随机推荐

  1. request参数获取,参数校验,参数处理

    需求: 1.post接口,需要在过滤器中进行参数校验,校验通过之后再执行方法 2.原有代码中使用x-www-form-urlencoded传参,新需求要使用json格式 3.原有代码校验过滤器使用Se ...

  2. windows下的Python的下载与安装

    Python的下载 Python下载要去官网下载,xdm,这里是网址 www.python.org 因为是外网所以打开下载会慢一些(不要着急的说) 这是python官网界面,跟着图片去下载(因为我这会 ...

  3. 03.python封装与解构

    封装与结构 基本概念 t1 = 1, 2 print(type(t1)) # 什么类型 t2 = (1, 2) print(type(t2)) Python等式右侧出现逗号分隔的多值的时候,就会将这几 ...

  4. vue3.0+vite项目搭建

    npm init vite-app <project-name> cd <project-name> 根据控制台的提示执行: npm install / yarn npm ru ...

  5. 服务限流 -- 自定义注解基于RateLimiter实现接口限流

    1. 令牌桶限流算法 令牌桶会以一个恒定的速率向固定容量大小桶中放入令牌,当有浏览来时取走一个或者多个令牌,当发生高并发情况下拿到令牌的执行业务逻辑,没有获取到令牌的就会丢弃获取服务降级处理,提示一个 ...

  6. 阿里云服务器ECS Ubuntu16.04 初次使用配置教程(图形界面安装)

    原文链接:? 传送门 前一阵子购买了阿里云的云服务器ECS(学生优惠),折腾了一阵子后对有些东西不太满意,所以就重新初始化了磁盘,刚好要重新安装图形界面,于是就顺手写了这么一篇文章. 第一次登陆服务器 ...

  7. 深度学习之BP算法

    1.介绍 人工神经网络(Artificial Neural Network,ANN)简称神经网络(NN),是在现代生物学研究人脑组织所取得成果的基础上提出来的.人工神经网络是大脑生物结构的数学建模,有 ...

  8. 《剑指offer》面试题32 - I. 从上到下打印二叉树

    问题描述 从上到下打印出二叉树的每个节点,同一层的节点按照从左到右的顺序打印.   例如: 给定二叉树: [3,9,20,null,null,15,7], 3 / \ 9 20 / \ 15 7 返回 ...

  9. 小程序onShareAppMessage有点迷

    小程序遇到的问题 起因 目前项目需求是分享时携带参数去进行裂变,但是在查看微信文档后发现有onShareAppMessage这个页面处理事件可以使用.事件可以使用return一个Object,用于自定 ...

  10. 五天学完MySQL打卡挑战 day01

    明天继续上传学习笔记和练习的Word文档 晚安~