【题解】P4688 [Ynoi2016] 掉进兔子洞

题意

P4688 [Ynoi2016] 掉进兔子洞

给定一个长度为 n 的序列和 m 个询问,每个询问给出 3 个区间 [l1,r1],[l2,r2],[l3,r3]。每次删去 一个 三个区间内共有的数,试求最终三个区间内的数的 个数和。询问之间互相独立。

注意每次仅删去 一个 共有的数而非将这种数全部删除。例如三个区间分别是 [1,2,2,3,3,3,3],[1,2,2,3,3,3,3],[1,1,2,3,3],最终只会删去 111223

1n,m105,1ai109

思路

转化成:莫队 + bitset

很难用莫队同时维护三个区间,考虑 转化 成用莫队分别求出三个区间,最后合并答案。

设最终一共会删去 k 个数,显然答案为 (r1l1+1)+(r2l2+1)+(r3l3+1)3k,问题转化为求最终删去的数的个数。

发现上面的问题实际上是求某一特定值在多个区间内分别出现的次数的最小值,难以直接用莫队维护。观察数据范围,ai109,显然需要离散化。整道题的突破口在于对离散化特殊处理,从而转化成 bitset 优化莫队。

不妨将 ai 离散化为整个序列中小于等于 ai 的值的个数,那么便可以用 bitset 优化莫队来维护了。

做法:

将每个操作拆分成三个询问。

cp 表示当前区间中值 p 的出现次数。不妨对于每一个操作维护一个 bitset,同时对当前区间维护一个 bitset,表示每个值是否出现过。端点移动时,若增加新数 x,则令 x+cx 为出现过,而后 cx+1;反之,cx1,且令 x+cx 为未出现过。

最后令当前区间的 bitset 与当前操作的 bitset 取交,最终 bitset1 的个数即为最终删去的数的个数。

原理:

原本相同的值离散化得到的值不同,即相同的值有一段连续的下标表示。现在离散化时令 ai 为序列中小于等于 ai 的数的个数,实际是将使用到的下标初始化为起始下标,x+cx 为现在使用到的下标。莫队时令 bitset 中下标为 x+cx 处为 1,相当于令 x 对应的值多出现 1 次。这样最终令 bitset 取交即为对每个值取最小的出现次数,取 1 的个数即为取删去的值的个数。反之同理。

由于空间限制,需要将询问分成多段处理。

代码

posted @   kymru  阅读(153)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 25岁的心里话
· 按钮权限的设计及实现
点击右上角即可分享
微信分享提示
主题色彩