飘花效果

简述摩尔投票

摩尔投票一般是用作求解序列“众数”(这和传统意义的众数不同,为了方便表示我加引号)(严格大于数个数的 \(\frac{1}{2}\))**的问题,时间复杂度为 \(\mathcal O(n)\),但是空间复杂度为 \(\mathcal O(1)\)

考虑到是严格大于,所以答案至多只有 \(1\)

一下考虑有解。

我们考虑把序列看作民众选举,通过抵消来求解这个数。

设当前这个严格“众数”为 \(num\),票数为 \(cnt\),当前这个人投了 \(x\)

  • \(cnt = 0\),那么 \(num'\) 已经抵消完了,此时 \(num \gets x\)\(cnt \gets 1\)

  • \(num \neq x\),说明这个人投了别人(可恶)!所以抵消,\(cnt \gets cnt - 1\)

  • \(num = x\),又有人投票了,那么 \(cnt\gets cnt + 1\)

感性理解,我们可以按照序列重新从小到大排序,如果存在严格大于 \(\lfloor{\frac{n}{2}}\rfloor\)\(num\),即使它和别人抵消,也至少会剩下 \(1\) 个。

并且我们发现,如果将序列分成前一半和后一半,设前一半的答案为 \(num1\),次数为 \(cnt1\);后一半的答案为 \(num2\),次数为 \(cnt2\)

那么众数 \(num\) 一定是次数较多的那一个。

比如 \(a = [1,2,2,2,2,2,1,1,1,1,1,1,1,1,5]\),我们划分成 \(b=[1,2,2,2,2,2]\)\(c=[1,1,1,1,1,1,1,1,5]\),那么 \(num1=2\)\(cnt1=5\)\(num2=1\)\(cnt2=8\),正确答案为 \(1\)

我们发现,这样抵消了答案还是 \(1\),剩余 \(cnt2=8-5=3>0\)


考虑求解出现次数严格大于 \(\lfloor\frac{n}{k}\rfloor\) 的数(\(1\le n\le 10^6\)\(1\le k\le 10\))。

可以证明,答案最多为 \(k - 1\) 个。

上面我们只有一个存储变量 \(num\),现在我们增加到 \(k-1\) 个存储变量,可以把它们放到数组里,然后对于这 \(k-1\) 个数都做一遍上面的三种情况即可。

时间复杂度为 \(\mathcal O(nk)\),但是空间复杂度为 \(\mathcal O(k)\),比普通排序或者离散化做的空间复杂度 \(\mathcal O(n)\) 优秀很多!


考虑求解区间严格“众数”。

上面已经总结了:

并且我们发现,如果将序列分成前一半和后一半,设前一半的答案为 \(num1\),次数为 \(cnt1\);后一半的答案为 \(num2\),次数为 \(cnt2\)

那么众数 \(num\) 一定是次数较多的那一个。

因此我们只要把这些信息放到线段树上,对于每次询问的 \([L,R]\),直接查询。

注意到不同的只有合并过程,也并不难写。

  • 这样时间复杂度为 \(\mathcal O(T\log n)\),空间复杂度为 \(\mathcal O(n)\)(不要忘了 \(4\) 倍空间,这里只是省略常数),其中 \(T\) 为询问次数。

  • 朴素的排序做法和离散化做法时间复杂度为 \(\mathcal O(T(n+\log n))\),复杂度升天,空间复杂度也就优化到了摩尔投票法的 \(\frac{1}{4}\)

posted @ 2025-06-28 19:15  2021zjhs005  阅读(13)  评论(0)    收藏  举报