莫队入门(理论篇)

在这你可以看到全oier中最低的莫队水平

普通莫队

例题:给出 \(N\) 个数和 \(M\) 个询问,对于每个询问,给出一个区间问这个区间出现次数最多的数是什么

这一题不管是用树状数组还是线段树都很难维护,于是这时我们就请出了我们的莫队算法。

我们先使用 \(2\) 个指针 \(l,r\) 去维护这个区间,我们可以发现我们可以轻易的通过 \([l,r]\) 来处理出 $ [l+1,r] ,[l-1,r],[l,r+1],[l,r-1]$ ,于是我们考虑暴力的移动指针到询问的区间来处理出答案

while(l>q[i].l)++col[a[--l]];
while(r<q[i].r)++col[a[++r]];
while(l<q[i].l)--col[a[l++]];
while(r>q[i].r)--col[a[r--]];

但是我们会发现这样暴力的移动还是 \(O(nm)\) 级别的,我们考虑优化它,我们可以发现对于 $ [1,2],[1000,1000],[1,3]$ 这三个区间我们需要移动 \(3996\) 次,而对于 \([1,2],[1,3],[1000,1000]\) 这三个区间来说只需要移动 \(1998\) 次,于是这启发我们把询问离线下来排序后在处理

可是应该怎么排序呢,我们考虑使用分块来辅助排序,假设我们的块长为 \(B\),因为我们分成了 \(\frac{B}{N}\) 块,对于左端点每块内要移动\(B\)次,对于右端点每块最多移动 \(N\) 次,所以复杂度是 \(O(M\frac{B}{N}+NB)\) ,当B取到 \(\sqrt{N}\)时最小,最终复杂度为 $ O((M+N)\sqrt{N})$

例题: P1494

思路:取到两只同颜色的袜子的方案数= \({\textstyle \sum_{i=1}^{N}col[i]*(col[i]-1)}(col[i] \ge 2)\) (cnt[i]表示颜色为i的袜子有几只),于是我们统计出每个数出现的次数,每次加数的时候,答案加上\(col[i]\),减数的时候,答案减去\(col[i]\)即可

posted @ 2023-08-25 22:49  Shxt_Plus  阅读(12)  评论(0)    收藏  举报