专栏文章
Solution P11982 | while seeing orderly streetlights
P11982题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @minl68z4
- 此快照首次捕获于
- 2025/12/02 04:12 3 个月前
- 此快照最后确认于
- 2025/12/02 04:12 3 个月前
思路借鉴了 @Daniel_lele,这里给出一些具体实现细节。
考虑根号重构,每次把接下来 次要修改的位置拿出来,令其下标序列为 。
Part 1
先计算至少有一个路灯在 中的二元组。构建一个新的序列如下:
其中 表示在 和 (均不含)之间的最高的路灯。所有 在这个块内均不会被修改,但是 的高度会被修改。
-
计算两个路灯都在 中的二元组把上述序列抠出来,跑单调栈,对每个路灯找到第一个高度 它的前驱,判断高度是否相等且二者均在 中即可。
-
计算只有一个路灯在 中的二元组每个 中的路灯最多只能和一个前驱、一个后继产生贡献(也就是这类贡献最多只有 个)每次修改一个路灯的时候,对这个路灯用线段树上二分,重新找其在整个序列中的前驱后继。但是修改一个 的高度可能会导致跨过它的二元组也失效/复活。可以在查询的时候利用之前的单调栈维护的信息, 暴力重新检查当前所有这类二元组是否合法。
Part 2
然后考虑两个路灯都不在 中的贡献。先直接在原序列中去掉被修改过的路灯,剩下的可以 单调栈跑出所有合法二元组,给它们编号,并用编号建立出它们的树形关系。
修改一个 的高度时会破坏一些原有的二元组。找到跨过 的两端点距离最近的二元组编号 ,那么从它开始往上的一条链会被标记为不再合法。
这可以用树剖+线段树维护。具体地,给树上所有点一个标记值 ,每次把一条链上的 加 (加入或撤销),并查询全局 的个数(即没有被标记过的点树),这通过维护区间最小值及其个数就能做到。
还有一个问题是怎么找 。这里提供一个算法:维护一个序列 ,对于每个二元组 ,让 加 ,让 减 。求 的时候相当于找到一个最小的 使 。于是把 求个前缀和后跑单调栈就可以线性预处理 。
现在来看看复杂度。重构的时候,线段树、树剖、单调栈,这些预处理全都是线性的;每次查询会把 个点拿出来再跑单调栈;一些 的东西忽略不计(实际上运行起来不能忽略不计),复杂度 。
听耳边熙熙攘攘的声音如风辨别不出你方位是我的瞳孔当看见一排工整有序的路灯低着头苏醒了
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...