数据结构做题记录
I. P3246 [HNOI2016] 序列
莫队
对于当前区间
设区间最小值位置为
发现剩下这部分答案满足可差分性,套路地设
思考如何求出
对称地,我们对左端点再次讨论即可。利用朴素的 ST 表维护区间最小值,时间复杂度
线段树
TODO。
II. P6604 [HNOI2016] 序列 加强版
设
这两部分贡献可以用普通版中莫队的做法中推的式子,具体地说就是考虑端点从
综上,我们可以
根据 Alex_wei 老师的说法,如上做法和 Cartesian 树是有关系的。相关题目:P6503 [COCI2010-2011#3] DIFERENCIJA。
III. #6376. 「HNOI2016」序列 二次加强版
朴素 ST 表无法通过,只能考虑
参见下一篇题解。
IV. P3793 由乃救爷爷
事实证明确定性的分块+ST 表跑得要比非确定性的 Cartesian 树慢得多()
我的实现中,ST 表+分块跑了 11.17s,而 Cartesian 树跑了 4.50s。
算法 1:ST 表+分块(确定性)
参考了 RI 的题解。RI 叫它二毛子()。
考虑将序列分成若干块,每块大小为
为了处理零散的段,我们预处理块内前缀最大值、块内后缀最大值。额外地,对于两端点在同一段的情况,我们需要额外处理一个
例如,
对于每次询问,如果两端点在同一块的情况,我们可以直接利用位运算找到最大值。
否则,先处理散块,再 ST 表查询整块。查询时间复杂度
综上,我们在
#include <bits/stdc++.h> using namespace std; // #define int long long using ull=unsigned long long; constexpr int MAXN=2e7+64, B=64; namespace GenHelper { unsigned z1,z2,z3,z4,b; unsigned rand_() { } } void srand(unsigned x) { } int read() { } int a[MAXN], pre[MAXN], suf[MAXN]; int f[19][MAXN/B+1]; ull val[MAXN]; #define bel(x) ((x+63)>>6) #define st(x) (((x-1)<<6)|1) #define ed(x) (x<<6) int n, m; int stk[MAXN], top; void build() { int bnum=bel(n); for (int i=1; i<=bnum; ++i) { pre[st(i)]=a[st(i)]; suf[ed(i)]=a[ed(i)]; for (int j=st(i)+1; j<=ed(i); ++j) pre[j]=max(pre[j-1],a[j]); for (int j=ed(i)-1; j>=st(i); --j) suf[j]=max(suf[j+1],a[j]); f[0][i]=pre[ed(i)]; } for (int i=1; i<=__lg(bnum); ++i) for (int j=1; j+(1<<i)-1<=bnum; ++j) f[i][j]=max(f[i-1][j],f[i-1][j+(1<<i-1)]); for (int i=1; i<=bnum; ++i) { top=0; for (int j=st(i); j<=ed(i); ++j) { if (j>st(i)) val[j]=val[j-1]; while (top&&a[j]>=a[stk[top]]) val[j]^=1ull<<stk[top--]-st(i); val[j]|=1ull<<j-st(i); stk[++top]=j; } } } int ask(int l, int r) { int x=bel(l), y=bel(r); if (x==y) return a[l+__builtin_ctzll(val[r]>>l-st(x))]; int ans=max(suf[l],pre[r]); if (x+1<y) { x++, y--; int t=__lg(y-x+1); ans=max({ans,f[t][x],f[t][y-(1<<t)+1]}); } return ans; } ull ans=0; signed main() { ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); unsigned s; cin>>n>>m>>s; srand(s); for (int i=1; i<=n; ++i) a[i]=read(); build(); int l, r; while (m--) { l=read()%n+1, r=read()%n+1; if (l>r) swap(l,r); ans+=ask(l,r); } cout<<ans; }
算法 2:Cartesian 树(依赖随机数据)
我们
我们知道,RMQ 问题可以转为 Cartesian 树上的 LCA 问题。本题中,由于数据随机,所以直接暴力跳 LCA 即可。时间复杂度期望
V. [AGC028B] Removing Blocks
VI. P5443 [APIO2019] 桥梁
首先,在
VII. P4314 CPU 监控
TODO。
VIII. P6242 【模板】线段树 3
IX. CF997E Good Subsegments
考虑套路地进行扫描线。
X. P5046 [Ynoi2019 模拟赛] Yuno loves sqrt technology I
XI. P5298 [PKUWC2018] Minimax
XII. P5048 [Ynoi2019 模拟赛] Yuno loves sqrt technology III
XIII. P6684 [BalticOI 2020 Day1] 小丑
XIV. P3247 [HNOI2016] 最小公倍数
操作分块+并查集。
具体地,将边按照
将询问对
对于整块,由于我们已经按照
记块大小为
XV. P5072 [Ynoi2015] 盼君勿忘
XVI. P2479 [SDOI2010] 捉迷藏
XVII. P5324 [BJOI2019] 删数
XVIII. P4513 小白逛公园
线段树维护区间最大子段和的板子。
XIX. P5327 [ZJOI2019] 语言
TODO。
XX. P5012 水の数列
TODO。
XXI. P5283 [十二省联考 2019] 异或粽子
转为异或前缀和是平凡的。
Solution 1:Trie
不妨将
我们维护四元组
于是,平凡地,我们对于
时间复杂度
Solution 2:持久化 Trie
类比 XXIX 超级钢琴 的套路,维护五元组
时间复杂度
XXII. CF125E MST Company
经典结论:设点集内 dfs 序最小和最大的点分别为
于是维护区间最大/次大/最小/次小 dfs 序即可。时间复杂度
XXIII. P5926 [JSOI2009] 面试的考验
这是三倍经验的第一题,我们考虑利用分块在
XXIV. CF765F Souvenirs
这是三倍经验的第二题,我们考虑利用权值线段树在
XXV. CF1793F Rebrending
这是三倍经验的第三题,我们考虑利用根号分治在
XXVI. UVA1619 感觉不错 Feel Good
XXVII. [ABC311G] One More Grid Task
XXVIII. P2839 [国家集训队] middle
XXIX. P2048 [NOI2010] 超级钢琴
XXX. CF1192B Dynamic Diameter
考虑利用线段树维护 Euler 序。
不妨设
引理 1
的 LCA 是 中深度最小的点。
引理 2 边权非负的时候,直径长度即为
也就是说,我们的答案就是
这启示我们,在线段树的节点上维护:
; ; ; ; 。
考虑合并两个节点
的合并
直接取四种情况的
的合并
取
, ,
的
考虑如何修改。对应区间上,我们有
; ; ; 。
加上 tag 后直接做就可以了。
时间复杂度是
XXXI. P8078 [WC2022] 秃子酋长
莫队的
考虑排列的逆排列。不难发现,时间复杂度的瓶颈在于插入,如果没有插入只有删除的话,可以利用双向链表做到
那么考虑不插入的回顾莫队:
首先建出整个序列对应的双向链表。
- 将询问按照左端点所在块编号为第一关键字(升序),右端点为第二关键字降序排序;
- 左端点处理到块
的时候,将 在双向链表中删除; - 记录此时的状态(此时右端点在
处),处理询问:- 将右端点移动到询问的右端点
; - 将左端点移动到询问的左端点
,回答询问; - 撤销左端点的移动,将左端点移回到
。
- 将右端点移动到询问的右端点
- 处理完
的询问后,将 3 中记录的状态还原,回到 3 处理下一块。
时间复杂度
XXXII. [ABC244Ex] Linear Maximization
对于
否则,我们利用一棵李超线段树维护。具体地说,注意到
就是求一些一次函数
时间复杂度
本题还有利用凸包的解法,详见 XXVIII。
XXXIII. P3309 [SDOI2014] 向量集
答案显然在凸包上。由于涉及区间询问,所以考虑线段树。
具体地说,我们在线段树的每个节点上维护一个凸包。查询时,在
考虑插入。如果每次插入我们都
但是可以在一个区间刚好满的时刻(也就是,加入的元素使得这个区间被填满)建立凸包,这样时间复杂度就正确了。正确性显然。
现在是 18:29,我看看我什么时候写完。
其实还是很好写的。code.
XXXIV. P5631 最小 mex 生成树
我们有两种解法。
整体二分
暴力的做:将边权等于
考虑整体二分,
时间复杂度
线段树分治
在边权上建立线段树,将一条边
XXXV. SP9576 Dynamic Graph Connectivity
XXXVI. P3899 [湖南集训] 更为厉害
XXXVII. P5227 [AHOI2013] 连通图
XXXVIII. CF1628E Groceries in Meteor Town
XXXIX. [ABC295G] Minimum Reachable City
XL. P6089 [JSOI2015] 非诚勿扰
XLI. [ABC342G] Retroactive Range Chmax
XLII. P3521 [POI2011] Tree Rotations 旋转树木
XLIII. [ABC341G] Highest Ratio
XLIV. P4093 [HEOI2016/TJOI2016] 序列
XLV. P4848 崂山白花蛇草水
XLVI. P5445 [APIO2019] 路灯
XLVII. P5689 [CSP-S2019 江西] 多叉堆
XLVIII. P10590 磁力块
IL. P10589 楼兰图腾
L. P3332 [ZJOI2013] K大数查询
LI. P2617 Dynamic Rankings
LII. P4175 [CTSC2008] 网络管理
首先套路地整体二分。
LII. P3242 [HNOI2015] 接水果
首先套路地整体二分。
考虑刻画路径
那么,只需要
即,
设
那么,只需要
即,
, 。 , 。
将路径
最后,扫描线即可。时间复杂度
LIII. P5344 【XR-1】逛森林
LIV. P5025 [SNOI2017] 炸弹
LV. [Nikkei 2019 Final F] Flights
题解。
LVI. P5471 [NOI2019] 弹跳
LVII. P3709 大爷的字符串题
直接回滚莫队即可,时间复杂度
LVIII. P1997 faebdc 的烦恼
LIX. P10638 BZOJ4355 Play with sequence
第二个操作可以看成是区间加与区间 chmax 的复合。于是只需要维护区间覆盖、区间加、区间 chmax 这三个操作就好了。
对于区间 chmax,我们用 segbeats 的套路,具体地说:
维护区间次小值
:无事可做,直接返回; :直接修改 即可; :递归处理。
吉如一老师证明了这么做的时间复杂度是
区间加和区间 chmax 是平凡的。只需要再维护一个区间最小值的数量
需要注意 tag 下传的顺序:先下传区间覆盖,再下传区间加,最后区间 chmax。区间覆盖之后要把区间加的 tag 清除掉。
似乎还有一种做法就是设 tag
代码。
LX. CF526F Pudding Monsters
LXI. CF997E Good Subsegments
LXII. P4462 [CQOI2018] 异或序列 / IL. CF617E XOR and Favorite Number
/fn
直接莫队即可。时间复杂度
LXIII. P9631 [ICPC2020 Nanjing R] Just Another Game of Stones
第一问可以直接上吉司机线段树。
LXIV. P10639 BZOJ4695 最佳女选手
Segbeats 板子题。我们维护区间的
:最大值,严格次大值,最大值的个数; :最小值,严格次小值,最小值的个数; :区间和。
以区间 chmax
:无事可做,直接返回; :直接修改 即可; :递归处理。
chmin 同理,对于 add 操作只需要维护一个 lazytag 即可。
需要注意的是,本题中同时有 chmax 和 chmin 操作,对于区间内只有 1~2 个本质不同的数的时候,需要特别处理一下。
同时需要注意 pushdown 时各个 tag 的顺序。
然后就做完了,代码很好写。时间复杂度可以证明是
LXV. P5354 [Ynoi2017] 由乃的 OJ
首先,
LXVI. P10637 BZOJ4262 Sum
TODO。
LXV. [AGC014E] Blue and Red Tree
LXVI. P3604 美好的每一天
套路地状态压缩,求一遍异或前缀和,问题转化为:
求满足
,且 或 的 数量。
显然可以用莫队。时间复杂度
LXVII. [ARC122D] XOR Game
LXVIII. P2468 [SDOI2010] 粟粟的书架
经典二合一。
对于前
对于剩下的数据,考虑持久化线段树。这样是
LVIII. P4559 [JSOI2018] 列队
经典结论是,将学生升序排序后,依次匹配
考虑怎么求答案。绝对值看起来很难受,我们不妨分成几段考虑。
对于
接下来就是
时间复杂度
LXIX. P3992 [BJOI2017] 开车
本文作者:Starrykiller
本文链接:https://www.cnblogs.com/Starrykiller/p/18194470/ds-practise
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步