当前位置: 首页 > news >正文

《擦除序列》线性时间做法题解

(最近把早些年零散写的题解收集整理一下)
关于这篇题解的背景:
先前已经有人用树(堆)写了题解,但是时间复杂度还没有达到极致。于是我写了这篇时间复杂度为 O ( n ) O(n) O(n) 的做法题解。

梳理题意

题目链接。
每次求剩下未被擦除的所有数字中,最大连续子段和的值且不能包含任何被擦除的位置。

解题思路

每次调用一遍最大连续子段和时间复杂度为 O ( n ) O(n) O(n) ,那么总的时间复杂度为 O ( n 2 ) O(n^2) O(n2),如果常数小一些能勉强过掉 60 % 60\% 60% 的数据;但是该题与最大连续子段和模板题的最大区别在于 1 ≤ a i ≤ 1 0 9 1≤a_i≤10^9 1ai109是的, a i a_i ai均为正数!
那么很明显我们每一次得到的最大连续子段一定与两个’X’(被擦掉的位置)或开头或结尾相邻,即尽可能向外延伸。
这时候我们也就没必要每一个区间都打一个最大值,仅记录符合上文要求的区间最大值即可。
但是又遇到了问题:每一次擦掉数字,区间会改变:一个区间分裂为两个区间。既要消除前者的影响,也要将答案再和后者取最大值。消除前者的影响至少需要对数级别的复杂度(可以使用平衡树),但那样不如直接使用线段树了。或许每一次都再打一遍最大值?那么成了 O ( n 2 ) O(n^2) O(n2) 算法,刚刚的分析也就没意义了。此时,“正难则反”,要从反面来思考问题。
从后向前,由擦除数字改为每次加入数字,于是就变成:两个区间合并为一个区间。由于前面所提 a i > 0 a_i>0 ai>0 ,所以两个子区间分别的和必然小于合并后区间的和,所以不会对答案产生影响,自然无需消除影响(想一想,为什么?)。
于是只需将合并后区间的和与当前最大值比大小。这样一遍加数一边打擂台就可以考虑到所有的需要考虑的区间。但是又应该如何在 O ( 1 ) O(1) O(1) 的复杂度完成区间的求和?
考虑 c n t [ i ] cnt[i] cnt[i] 代表区间号为 i i i 的区间和; C N T CNT CNT 代表当前使用过的最大区间号,因此再加一就是一个空余区间号(类似于链式前向星的计数器); L E F T [ i ] LEFT[i] LEFT[i] 表示区间号为 i i i 的区间向左能扩展到的位置(个人程序实现时为方便而-1); R I G H T [ i ] RIGHT[i] RIGHT[i] 表示区间号为 i i i 的区间向右能扩展到的位置(个人程序实现时为方便而+1); l [ i ] l[i] l[i] 表示向左能扩展到位置 i i i 的区间的区间号; r [ i ] r[i] r[i] 表示向右能扩展到位置 i i i 的区间的区间号;而 a n s [ i ] ans[i] ans[i] 表示在 p [ i ] p[i] p[i] 被擦掉以后的答案。
或许你已经注意到: l l l L E F T LEFT LEFT r r r R I G H T RIGHT RIGHT 是维护双射的数组。(在编写与调试此类问题时极需要耐心)

具体实现

于是逆序枚举:当每一个被擦掉的 p [ i ] p[i] p[i] “还原回来”,有以下操作:
1.更新 c n t cnt cnt 数组。每一个 p [ i ] p[i] p[i] 还原回来时都将原本两个独立的区间合并(可以为空),而 p [ i ] p[i] p[i] 则分别是这两个集合向左和向右能扩展到的位置,所以它们的区间号分别是 l [ p [ i ] ] l[p[i]] l[p[i]] r [ p [ i ] ] r[p[i]] r[p[i]] ,再加上 a [ p [ i ] ] a[p[i]] a[p[i]],因此:

cnt[++CNT]=cnt[l[p[i]]]+cnt[r[p[i]]]+a[p[i]];

2.维护 L E F T LEFT LEFT R I G H T RIGHT RIGHT 数组。在最开始时均初始化为 − 1 -1 1 。如果 L E F T [ r [ p [ i ] ] ] LEFT[r[p[i]]] LEFT[r[p[i]]] 为-1,说明原左侧区间为空,此时应当将现区间能扩展到的最左位置更新为 p [ i ] − 1 p[i]-1 p[i]1 ;否则不是空区间,那么最左端应该是左侧区间的左端即 L E F T [ r [ p [ i ] ] ] LEFT[r[p[i]]] LEFT[r[p[i]]] R I G H T RIGHT RIGHT 数组同理。于是得到:

if(LEFT[r[p[i]]]==-1)LEFT[CNT]=p[i]-1;
else LEFT[CNT]=LEFT[r[p[i]]];
if(RIGHT[l[p[i]]]==-1)RIGHT[CNT]=p[i]+1;
else RIGHT[CNT]=RIGHT[l[p[i]]];

3.维护 l l l r r r 数组。一开始均为 0 0 0 (我的区间号从 1 1 1 标起, 0 0 0 默认为空区间),由于 l l l L E F T LEFT LEFT r r r R I G H T RIGHT RIGHT 双向映射,而在第2步中 L E F T LEFT LEFT R I G H T RIGHT RIGHT 已经更新,所以只需要维护双射即可(若解释理解也可以,但是这样思考起来更方便):

l[LEFT[CNT]]=r[RIGHT[CNT]]=CNT;

4.更新 a n s ans ans 数组:

ans[i-1]=max(ans[i],cnt[CNT]);

总结反思

我的方法时间复杂度为 O ( n ) O(n) O(n) ,利用 a i > 0 a_i>0 ai>0 的条件避免冗余比较,总计只会考虑 n n n 个区间。虽然它只能处理 a i > 0 a_i>0 ai>0 ,而树(堆)的做法似乎没有限制,然而我相信出题人既然给出了 a i > 0 a_i>0 ai>0 的条件,那必定有它存在的价值,值得我们去探究,成为我们做题乃至优化的依据之一。一旦数据加到百万甚至千万级别, O ( n l o g n ) O(n\ log\ n) O(n log n) 的做法就有可能超时。最后,希望同学们不选得分最高的,要选最适合自己的算法!

注:修改于2024年8月6日。

#include <bits/stdc++.h>
#define int long long
using namespace std;int a[100010],n,p[100010],ans[100010],l[100010],r[100010],cnt[100010],CNT,LEFT[100010],RIGHT[100010];signed main(){cin>>n;for(int i=1;i<=n;++i){cin>>a[i];}for(int i=1;i<=n;++i)cin>>p[i];memset(LEFT,-1,sizeof(LEFT));memset(RIGHT,-1,sizeof(RIGHT));for(int i=n;i>=1;--i){cnt[++CNT]=cnt[l[p[i]]]+cnt[r[p[i]]]+a[p[i]];if(LEFT[r[p[i]]]==-1)LEFT[CNT]=p[i]-1;else LEFT[CNT]=LEFT[r[p[i]]];if(RIGHT[l[p[i]]]==-1)RIGHT[CNT]=p[i]+1;else RIGHT[CNT]=RIGHT[l[p[i]]];l[LEFT[CNT]]=r[RIGHT[CNT]]=CNT;ans[i-1]=max(ans[i],cnt[CNT]);}for(int i=1;i<=n;++i)cout<<ans[i]<<" ";return 0;
}

相关文章:

  • 点云(Point Cloud)介绍
  • 可发1区的超级创新思路(python 、MATLAB实现):基于区域注意力双通道MABMA的时间序列预测模型
  • Megatron-Core 进行大规模语言模型(LLM)训练【专题2】
  • Vivado比特流生成、下载及板级验证操作步骤
  • 【C++算法】64.字符串_字符串相乘
  • 服务部署丨通过Docker部署AutoBangumi+qBittorrent实现自动追番
  • sql之DML(insert、delete、truncate、update、replace))
  • 前端工程化之自动化测试
  • 聊聊Doris的数据模型,如何用结构化设计解决实时分析难题
  • 【笔记】网路安全管理-实操
  • element-plus样式失效的原因总结
  • 机器学习(1)— 开发环境安装
  • 每天学一个 Linux 命令(25):more
  • n8n 中文系列教程_02. 自动化平台深度解析:核心优势与场景适配指南
  • Manus技术架构、实现内幕及分布式智能体项目实战 线上高级实训班
  • OzGIS:地理信息分析与处理软件
  • OpenFeign终极指南:超时控制、重试策略、拦截器与自定义Starter
  • VBA 调用 dll 优化执行效率
  • Linux字符设备驱动
  • Linux下 文件的查找、复制、移动和解压缩
  • 管理规模归零,华夏基金“ETF规模一哥”张弘弢清仓卸任所有产品
  • 一女子称醉酒后疑似被性侵,长沙警方通报:嫌犯邱某某已被刑拘
  • 西北政法大学推无手机课堂,有学生称要求全交,学校:并非强制
  • 融创中国披露二次境外债重组方案:总规模约95.5亿美元债全额转股权,孙宏斌部分受限股票6年内不得处置
  • 霸王茶姬成美股“中国茶饮第一股”:首日涨近16%,市值60亿美元
  • 美国佛罗里达州立大学发生枪击事件