Cut the Sequence

news/2024/11/19 20:20:02/文章来源:https://www.cnblogs.com/zhouruoheng/p/18555175

Cut the Sequence

P10977 Cut the Sequence

前言

单调队列优化 dp 的好题,思维难度大细节多。因为觉得自己看不懂其他题解,在看完 y 总的讲解后豁然开朗,所以写这篇题解来巩固一下。包括完整的细节分析和思考过程,或许很多大佬都不需要 qwq。叠甲完毕,下面开始正文。

分析

先考虑无解的情况,将单个元素分成段,每段的和最小,如果还是大于 \(m\) 肯定无解。所以当存在 \(a_i > m\) 时,输出 \(-1\)

状态表示

题意和给出的信息都很简单,看 \(n\) 的范围判断大致是 \(O(n)\) 或者 \(O(n\log(n))\) 的算法。因为要满足限制且最优化答案,不难想到动态规划来解决。第一维显然是考虑前 \(i\) 个数,通过复杂度分析判断不能存在第二维,实际上也并不需要。所以,设 \(f_i\) 表示只考虑前 \(i\) 个数划分成若干段,每段的和不超过 \(m\) 的最小代价,代价为每一段的最大值之和。

状态转移

考虑 \(f_i\) 的集合划分依据,显然是最后一段的长度,设上一个状态为 \(f_j\),最后一段就是 \([j+1,i]\),其中 \(0 \le j \le i-1\),而且要满足限制,所以 \(\sum_{k=j+1}^{i} a_k \le m\),最后一段产生的贡献为 \(\max_{k=j+1}^{i} a_k\)。状态转移方程即为:

\[ f_i=\min_{0 \le j \le i-1 \land \sum_{k=j+1}^{i} a_k \le m} (f_j+\max_{k=j+1}^{i} a_k) \]

优化

上面这个方程显然是 \(O(n^2)\) 的,不足以通过此题。看式子好像也没啥能转化的,考虑一些性质来优化。

首先注意到 \(f\) 是单调不减的,也就是说 \(f_{i-1} \le f_i\),简单证明下:

设最后一段的贡献为 \(a_{max}\),考虑在末尾加上 \(a_i\)

  • \(a_i\) 加入最后一段,
    • \(a_i > a_{max}\) 时,有 \(f_i=f_{i-1}-a_{max}+a_i\)
    • \(a_i \le a_{max}\) 时,有 \(f_i=f_{i-1}\)
  • \(a_i\) 自己新开一段,有 \(f_i=f_{i-1}+a_i\)

因为序列中的数大于等于 \(0\),所以有 \(f_{i-1} \le f_i\),即 \(f\) 单调不减。

蓝书上的话:

DP 转移优化的指导思想就是及时排除不可能的决策,保持候选集合的高度有效性和秩序性。

所以不妨设 \(j\) 为转移的最优决策,考虑其满足什么样的性质。

\[ f_i=\min(f_j+a_{max}) \]

img

设最后一段的贡献为 \(a_{max}\),设 \(k_0\) 为满足 \(\sum_{k=j+1}^{i} a_k \le m\) 的最小的 \(j\)\(a_{max_1}\)\([k_0,i]\) 的最大值,下标为 \(k_1\)。次大值为 \(a_{max_2}\),下标为 \(k_2\)。所以:

\[ \max_{k=k_0+1}^{i} a_k=a_{max_1}=a_{k_1} \]

\[ \max_{k=k_1+1}^{i} a_k=a_{max_2}=a_{k_2} \]

\[ \max_{k=k_2+1}^{i} a_k=a_{max_3}=a_{k_3} \]

\[ \dots \]

  • \(k_0 \le j < k_1\) 时,\(a_{max}=a_{max_1}\)\(f_j\) 最小值肯定是在 \(j=k_0\) 时,所以最优的 \(j\)\(k_0\)
  • \(k_1 \le j < k_2\) 时,\(a_{max}=a_{max_2}\),最优的 \(j\)\(k_1\)
  • \(k_2 \le j < k_3\) 时,\(a_{max}=a_{max_3}\),最优的 \(j\)\(k_2\)

所以最优决策 \(j\)\(k_0,k_1,k_2,\dots\)

所以 \(j\) 要成为最优决策,除了要满足 \(\sum_{k=j+1}^{i} a_k \le m\) 外,还要满足下面条件之一:

  1. \(k_0\) 时,\(k_0\) 为满足 \(\sum_{k=j+1}^{i} a_k \le m\) 的最小的 \(j\)
  2. \(k_1,k_2,k_3,\dots\) 时,满足 \(a_j=\max_{k=j}^{i} a_k\)

情况 \(1\),只需要用双指针求 \(k_0\)

情况 \(2\),可以用单调队列维护 \(k_1,k_2,\dots\),只需要保证 \(a_j\) 单调递减。可是有一个问题,\(f_j+a_{max}\) 在单调队列中并不一定是单调的,所以要用其他东西维护,要支持加入元素,删除元素,求最小值,可以用平衡树,当然不用自己写,可以用 set,但是值可能有重复,所以使用 multiset。\(k_p\) 为队列中的元素,能产生的贡献为 \(f_{k_p}+a_{k_{p+1}}\)

有一个细节,只有当单调队列中的元素大于一时,才能出现第二种情况,思考一下就能理解。

code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <vector>
#include <queue>
#include <map>
#include <set>
using namespace std;
typedef long long ll;
const int N=1e5+5;
int n;
ll m;
ll a[N],f[N];
int q[N];
multiset<ll> st;
void solve()
{cin>>n>>m;for(int i=1;i<=n;i++){cin>>a[i];if(a[i]>m) //无解的情况{cout<<"-1\n";return ;}}int l=1,r=0;ll sum=0;for(int i=1,j=1;i<=n;i++){sum+=a[i];while(sum>m) {sum-=a[j++];while(l<=r&&q[l]<j) {if(l<r) st.erase(f[q[l]]+a[q[l+1]]);l++;}}while(l<=r&&a[q[r]]<=a[i]) {if(l<r) st.erase(f[q[r-1]]+a[q[r]]);r--;}q[++r]=i;if(l<r) st.insert(f[q[r-1]]+a[q[r]]);f[i]=f[j-1]+a[q[l]];//处理后j=k0+1if(st.size()) f[i]=min(f[i],*st.begin());}cout<<f[n]<<'\n';
}
int main()
{#ifndef ONLINE_JUDGEfreopen("1.in","r",stdin);freopen("1.out","w",stdout);#endif ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);solve();return 0;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/836978.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

20222408 2024-2025-1 《网络与系统攻防技术》实验五实验报告

1.实验内容 1.1实验要求 (1)选择一个DNS域名进行查询,获取如下信息:DNS注册人及联系方式、该域名对应IP地址、IP地址注册人及联系方式、IP地址所在国家、城市和具体地理位置。 (2)尝试获取QQ中某一好友的IP地址,并查询获取该好友所在的具体地理位置。 (3)使用nmap开源…

[考试记录] 2024.11.19 noip模拟赛17

T1 选取字符串warning❗:本题解 前缀 含量过高。挺典的 kmp。考虑到题目中的串都是一个串的前缀,那么所选出来的串,他们的前缀一定是最短的那个串。不妨直接枚举每一个前缀,也就是枚举每一个串,看他们是否可以作为前缀出现,hash即可,复杂度 \(\mathcal{O}(N^2)\)。换个…

【淘汰9成NLP工程师的常识题】多头注意力相对于多头注意力有什么优势?

【淘汰9成NLP工程师的常识题】多头注意力相对于多头注意力有什么优势? 重要性:★★★ 💯 这是我【淘汰9成NLP工程师的常识题】多头注意力相对于多头注意力有什么优势? 重要性:★★★ 💯这是我常用的一个面试题。看似简单的基础常识题,但在面试中能准确回答的不足10% …

多校A层冲刺NOIP2024模拟赛24

多校A层冲刺NOIP2024模拟赛24\(T1\) A. 选取字符串 \(100pts\)考虑建出失配树,然后等价于询问 \(\sum\limits_{S \sube \{ 0,1,2, \dots ,n \},|S|=k}dep_{\operatorname{LCA}\{ S \}}^{2}\) 。不妨从 \(\operatorname{LCA}\) 的角度考虑,统计 \(x\) 能作为多少个 \(|S|\) 的…

在微信中使用AI聊天机器人

微信是中国最流行的社交通讯软件,具有庞大的用户基础。ChatGPT是由 OpenAI 开发的、当前最先进的AI聊天机器人,ChatGPT 尤其是在理解和生成自然对话方面表现出色,能够进行流畅且连贯的交流。对中国人而言,将 ChatGPT 集成到微信中,可以在一个熟悉的环境中体验到最新的人工…

protodep踩坑

在使用微服务框架go-zero时,服务拆分比较多,每更新一个服务的proto文件,都要手动复制pb文件到调用的服务里面,新系统开发的时候决定用protodep解决这个问题。 protodep 是一款专为Protocol Buffers接口描述语言文件设计的依赖管理工具。它解决了在使用gRPC时,如何有效控制…

虚幻4 蓝图无法保存 解决方法

蓝图类只能存放在 Blueprints文件夹内,创建在其他文件夹的蓝图类无法保存。 可以看到无法将蓝图拖动到其他文件夹内。这是一个存放在其他文件夹下的蓝图类:当尝试按Ctrl+shift+A保存时,将出现如下错误:解决方法是,将当前蓝图删除(注意,如果该蓝图从某个C++类继承而来,那…

理解进程调度时机跟踪分析进程调度与进程切换的过程

张晓攀+原创作品转载请注明出处+《Linux内核分析》MOOC课程https://mooc.study.163.com/course/1000029000 实验八——理解进程调度时机跟踪分析进程调度与进程切换的过程 一、理解Linux系统中进程调度的时机 在 Linux 内核中,schedule() 函数是核心的进程调度机制。它的主要作…

李继刚Lisp提示词灵感之源:压缩推动进步

探秘李继刚Lisp提示词压缩表达的灵感来源:德国计算机科学家尤尔根施密德胡伯提出,智能系统通过学习新技能来更高效地预测或压缩信息,这种内在动力推动了好奇心和创造力的发展,适用于从婴儿探索世界到科学家发现新规律的各种场景。前面在文章《 访谈李继刚:从哲学层面与大模…

java:找不到符号 符号:变量:log

原文链接:https://blog.csdn.net/zhanghaoninhao/article/details/129180810问题:java:找不到符号 符号:变量:log环境:springboot idea解决方法:在idea中,点击file-Settings,打开配置页面,如图红框位置,输入: -Djps.track.ap.dependencies=false

【SolidWorks 2024下载与安装教程】

‌SolidWorks 2024是一款由达索系统(Dassault Systemes)开发的三维CAD软件,广泛应用于机械设计、产品开发、工程设计、制造等领域。‌ 该软件以其强大的功能和易学易用的特点,深受工程师和设计师的喜爱。SolidWorks 2024在2024版本中引入了一系列新功能和改进,旨在提高设计效…