带修改莫队
请确保您已经会普通莫队算法了。如果您还不会,请先阅读前面的“普通莫队算法”。
特点¶
普通莫队是不能带修改的。
我们可以强行让它可以修改,就像 DP 一样,可以强行加上一维 时间维, 表示这次操作的时间。
时间维表示经历的修改次数。
即把询问 [l,r] 变成 [l,r,time]。
那么我们的坐标也可以在时间维上移动,即 [l,r,time] 多了一维可以移动的方向,可以变成:
- [l-1,r,time]
- [l+1,r,time]
- [l,r-1,time]
- [l,r+1,time]
- [l,r,time-1]
- [l,r,time+1]
这样的转移也是 O(1) 的,但是我们排序又多了一个关键字,再搞搞就行了。
可以用和普通莫队类似的方法排序转移,做到 O(n^{\frac{5}{3}})。
这一次我们排序的方式是以 n^{\frac{2}{3}} 为一块,分成了 n^{\frac{1}{3}} 块,第一关键字是左端点所在块,第二关键字是右端点所在块,第三关键字是时间。
还是来证明一下时间复杂度:
- 左右端点所在块不变,时间在排序后单调向右移,这样的复杂度是 O(n);
- 若左右端点所在块改变,时间一次最多会移动 n 个格子,时间复杂度 O(n);
- 左端点所在块一共有 n^{\frac{1}{3}} 中,右端点也是 n^{\frac{1}{3}} 种,一共 {n^{\frac{1}{3}}}\times{n^{\frac{1}{3}}}=n^{\frac{2}{3}} 种,每种乘上移动的复杂度 O(n),总复杂度 O(n^{\frac{5}{3}})。
例题¶
我们不难发现,如果不带操作 1(修改)的话,我们就能轻松用普通莫队解决。
但是题目还带单点修改,所以用 带修改的莫队。
先考虑普通莫队的做法:
- 每次扩大区间时,每加入一个数字,则统计它已经出现的次数,如果加入前这种数字出现次数为 0,则说明这是一种新的数字,答案 +1。然后这种数字的出现次数 +1。
- 每次减小区间时,每删除一个数字,则统计它删除后的出现次数,如果删除后这种数字出现次数为 0,则说明这种数字已经从当前的区间内删光了,也就是当前区间减少了一种颜色,答案 -1。然后这种数字的出现次数 -1。
现在再来考虑修改:
- 单点修改,把某一位的数字修改掉。假如我们是从一个经历修改次数为 i 的询问转移到一个经历修改次数为 j 的询问上,且 i<j 的话,我们就需要把第 i+1 个到第 j 个修改强行加上。
- 假如 j<i 的话,则需要把第 i 个到第 j+1 个修改强行还原。
怎么强行加上一个修改呢?假设一个修改是修改第 pos 个位置上的颜色,原本 pos 上的颜色为 a,修改后颜色为 b,还假设当前莫队的区间扩展到了 [l,r]。
- 加上这个修改:我们首先判断 pos 是否在区间 [l,r] 内。如果是的话,我们等于是从区间中删掉颜色 a,加上颜色 b,并且当前颜色序列的第 pos 项的颜色改成 b。如果不在区间 [l,r] 内的话,我们就直接修改当前颜色序列的第 pos 项为 b。
- 还原这个修改:等于加上一个修改第 pos 项、把颜色 b 改成颜色 a 的修改。
因此这道题就这样用带修改莫队轻松解决啦!
参考代码
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 | |
build本页面最近更新:,更新历史
edit发现错误?想一起完善? 在 GitHub 上编辑此页!
people本页面贡献者:StudyingFather, Backl1ght, countercurrent-time, Ir1d, greyqz, MicDZ, ouuan
copyright本页面的全部内容在 CC BY-SA 4.0 和 SATA 协议之条款下提供,附加条款亦可能应用