专栏文章

题解:P8987 [北大集训 2021] 简单数据结构

P8987题解参与者 2已保存评论 2

文章操作

快速查看文章及其快照的属性,并进行相关操作。

当前评论
2 条
当前快照
1 份
快照标识符
@miopoi7e
此快照首次捕获于
2025/12/02 23:06
3 个月前
此快照最后确认于
2025/12/02 23:06
3 个月前
查看原文
感觉这题还是比较套路的,放在当今 CNOI 大家肯定都能切穿了吧。
先考虑这样一个问题:如果 aa 的初始值满足 a1=a2==an=Aa_1=a_2=\cdots = a_n = A 怎么办?
考虑将 min\min 拆开(这种套路在涉及很多取 min\min 的数据结构题中比较常见,举个例子就是 min(a,min(b,c)+d)=min(a,b+d,c+d)\min(a,\min(b,c)+d) = \min(a,b+d,c+d),只有最外层一个 min\min 方便使用数据结构维护)。
tt当前操作 22 执行的次数,并且维护辅助数组 bb。当执行了 11 操作(最开始我们可以认为 ai=+a_i = +\infty,并且执行了 v=Av=A11),对于所有的 bb 执行 bimin{bi,vit}b_i \leftarrow \min\{b_i,v-it\}
那么查询的时候 ai=bi+ita_i=b_i+it,所以只需要维护 bb 的区间和。
显然 bib_i 是若干条 y=vtxy=v-tx 的线构成的凸包。平衡树动态维护凸包肯定是可以的,但是发现斜率是递减的,所以维护一个栈就行。
所以为什么没有这个的部分分??很奇怪啊。
回到原题,如果初始的时候假设 ai=+a_i=+\infty 那么上面的操作肯定还是对的,但是会算大了,因为每个 ii 在最开始会有 biaib_i \leftarrow a_i。那咋办?
显然这个初始的 aia_i 在某个时刻之后就没用了,可以直接套用上面那个做法。找到这个时刻 limilim_i,在 limilim_i 之前我们不需要考虑 11 操作,只是简单的区间加;在 limilim_i 之后我们不用考虑初始值,可以用简单的区间赋值线段树维护。
那么,怎么找到这个 limlim
思路 1:我们对于每次操作 11,没有把原有的 aa 覆盖掉需要初始的 aivita_i \le v- it。前 tmptmp 时刻都没更新,等价于这些限制都成立,所以我们要对于一大堆 (v,t)(v,t)vitv-it 的最小值。显然可以整体二分,这样是 O(nlog2n)O(n \log^2 n) 的。
思路 2:考虑直接上 KTT。容易势能分析得到复杂度为 O(nlog2n)O(n \log^2 n)。感觉不太好写,常数可能还不小。这样还不用离线,不好评价。
思路 3:在思路 1 中,为什么要用李超树呢?因为斜率是递减的,所以我们可以把凸包建出来,而建立凸包的过程只用到了栈,所以这一部分是 O(nlogn)O(n \log n);查询的时候也不用在凸包上二分,因为我们可以通过手段使得查询的横坐标是递增的,那么就可以使用双指针来做到线性。因此我们的整体二分在 O(nlogn)O(n \log n) 完成。

评论

2 条评论,欢迎与作者交流。

正在加载评论...