1 条题解
-
0
一、题目简化
有一个城市,有 个建筑物(编号 到 ), 号是市中心。
建筑物之间有 条双向道路,整个城市的地图是一个“仙人掌”——意思是每条边最多在一个环上,并且从市中心可以到所有建筑物。每个建筑物卖一种拉面,油腻程度是 (正整数)。
特殊情景:
rin 在建筑物 时,假设从市中心 到 的所有简单路径上的道路都被堵死了,那么 rin 就被困在 所在的连通块里(无法离开这个块)。在这个连通块里,rin 可以吃到这个块里所有建筑物的拉面(多次经过就多次吃)。
问题:
给定 和油腻值上限 ,以及 ( 或 ),问在这个连通块中:- 油腻值 的拉面种类中:
- 如果 :出现次数为 偶数 的种类数
- 如果 :出现次数为 奇数 的种类数
二、关键转化
1. 连通块是啥?
在仙人掌图中,删掉 到 的所有简单路径的边后, 所在的连通块,其实就是 DFS 树中 的某棵子树。
具体来说:
- 对图做 DFS(根为 ),得到每个点的进入时间 和离开时间 。
- 从 往上找,找到第一个点 ,它所在的环能通到 到 路径上的更早的点,那么连通块就是 的子树(去掉那些能直接回到更上面的部分)。
- 实际上可以证明:这个连通块在 DFS 序上是 一个连续区间 。
所以问题变成:
给定一个区间(DFS 序区间),问区间内油腻值 的拉面种类,按出现次数奇偶性分类统计。
2. 问题变成区间数颜色(带奇偶)
我们有 个位置(DFS 序),每个位置有一个油腻值。
给一个区间 和 ,求:- 油腻值 的颜色中,出现次数为偶数的颜色数()
- 油腻值 的颜色中,出现次数为奇数的颜色数()
三、算法选择
直接对每个询问扫区间太慢,因为 可达 。
1. 莫队算法
- 把询问按区间排序,用两个指针 在序列上移动,动态维护区间内每种油腻值的出现次数。
- 移动时,当某个油腻值的次数变化时,更新它的奇偶性。
2. 值域分块
油腻值 ,询问的 。
我们维护:- :油腻值 在当前区间出现次数的奇偶( 偶, 奇)
- 把值域分成块,每块维护块内 出现次数为奇数的种类数。
插入/删除一个值 时:
- 如果原来出现次数是奇数,加入后变偶数,那么奇数种类数减
- 如果原来是偶数,加入后变奇数,那么奇数种类数加
查询时:
- 对值域块扫描,对油腻值 的块,累加奇数种类数,就能得到“油腻值 且出现次数为奇数的种类数”。
- 偶数的种类数 (油腻值 的总种类数)(奇数种类数)。总种类数可以类似用值域分块维护。
四、步骤总结
-
DFS 建树
得到 DFS 序,把每个点对应的连通块映射成 DFS 序上的区间。 -
莫队处理
把询问按区间排序,用双指针维护区间,同时用值域分块维护奇偶信息。 -
回答询问
根据 输出奇数或偶数种类数。
五、复杂度
- 莫队移动:
- 值域分块查询: 每次
- 总复杂度:,可过 数据。
- 油腻值 的拉面种类中:
- 1
信息
- ID
- 3209
- 时间
- 3000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者