【算法】莫队

莫队是永远也卡不住的。
                         —————— 许多dalao

很久以前 老师讲了莫队,目的是让我们理解分块思想,当时没时间做笔记(其实是懒的),现在来补上OVO。

使用范围(纯属个人理解)

  1. 区间求元素种类个数,每种种类元素个数……

  2. 一些看似线段树能做的题但实际上不满足加和性质的题。

  3. 大部分树状数组能做的题。

(如果有错误请大佬轻点打(\doge))

大概需要的东西

  1. 分块(我不会)

  2. 结构体排序(这个应该是得心应手了)

  3. 疯狂卡常小技巧(不一定需要)

  4. 一个清明的脑子和一双别老手残的手(这个很重要)

思路过程

先分块,再排序,最后四个 while 结束一切。

放个例题(老师的例题)

洛谷 P1494 [国家集训队]小Z的袜子

题意概括

有一个长度为 \(n\) 的序列,里面的元素为 \(c_i\) ,有 \(m\) 组询问,每次询问给出 \(l\)\(r\)

求如果在 \([l,r]\) 里任意选两个数字选到相同数字的概率是多少,

输出答案以分数形式存在。

数据范围:\(n,m\in[1,50000]\)\(c_i,l,r\in[1,n]\)

分析

很明显,这道题符合之前我说的莫队适用情况。

这时候,就是莫队发威的时候了!!(雾)

注意:以下过程可能会让人不明不白的,但我会在后面细讲的。

First

以每个块为 \(\sqrt n\) 的大小分成 \(\sqrt n\) 个块 。

Second

以每个查询区间的左端点所在块顺序排序,

如果左端点所在块相同,就按照右端点所在块的序数奇偶性排序:

若右端点在奇数块,顺序排序;

若右端点在偶数块,倒叙排序。

Third

开始遍历所有查询区间,设 \(l\)\(r\) 两个指针作为遍历到的区间,

初始 \(l = 1\)\(r = 0\) 代表现在所在区间不存在,

然后从排好序的查询区间作为询问区间 \(ql\)\(qr\)

如果 \(l < ql\),就让 \(l\) 向右移动直到与 \(ql\) 重合;

如果 \(l > ql\),就让 \(l\) 向左移动直到与 \(ql\) 重合;

如果 \(r < qr\),就让 \(r\) 向右移动直到与 \(qr\) 重合;

如果 \(r > qr\),就让 \(r\) 向左移动直到与 \(qr\) 重合,

同时让记录 \(l\)\(r\) 之间所有种类元素的个数的数组 \(cnt\) 随遍历到的数字来加减计数。

Last

最后求出概率的分母与分子,约分后全部输出。

解释

Third

先说第三步,便于下面的解释。

一开始,还没有遍历的时候,\(l\)\(r\) 是初始化的,大概是这样:

请不要在意奇怪的数字

很明显,此时 \(l\)\(r\) 之间没有任何元素 。

我们假定 \(ql = 2\)\(qr = 6\)

而此时 \(l\) 小于 \(ql\),所以 \(l\) 向右移动直到与 \(ql\) 重合 。

现在是这样的:

关于更新 \(cnt\) 数组

每次扫到一个数字(无论是 \(l\) 还是 \(r\)),

如果之前扫到过,就说明 \(cnt\) 数组已经记录下来了这个元素,而现在再扫到说明要将这个元素从 \(l\)\(r\) 这个区间中删去,这时候 \(cnt--\)

如果之前没有扫到过,就说明 \(cnt\) 数组没有记录下来,而现在扫到说明要将这个元素从 \(l\)\(r\) 这个区间中加上,这时候 \(cnt++\)

现在继续模拟:

既然 \(l\)\(ql\) 已经重合了,那么现在需要更新的是 \(r\) 的位置,于是 \(r\) 开始向 \(qr\) 靠拢直到重合:

于是现在 \(cnt\) 数组里存的是 \(ql\)\(qr\) 的统计值,剩下的只需要在统计的时候按照求概率的公式来就行了,记得用 \(ans\) 数组记录下当前值,

毕竟查询下一个区间是在当前区间的基础下完成的。

First

分块不必多说,如果不懂就看看 这个

分块的作用大概就是让上面说的两个指针 \(l\)\(r\) 每次不会移动太大的距离:

\(r\) 从头到尾一直是从左到右的,而 \(l\) 则是在一个块里来回移动咣当。

Second

莫队的奇偶性排序简直是最玄学的,经老师的一番解释,我大约明白了是怎么回事。

但我说不出来……

不过这不重要,最重要的是知道要这么做就好啦(护头,大佬轻点打/doge)

Last

个人 jiao 得,这个才是最难得(确信脸),如果不会请看大佬们的题解(这个不属于莫队里的)

最后

如果看到这里还不懂的话,就看看这篇吧,

反正我是看这篇才会的(老师讲课永远 emmmm 懂得)

膜拜大佬 %%%

posted @ 2020-12-27 16:40  _Scaley  阅读(144)  评论(3编辑  收藏  举报