算法介绍
莫队算法,简单说就是基于分块进行暴力
莫队算法,是由前国家队队长莫涛在役时创造的,为数不多几种在役选手在比赛或平时训练中创造并广为流传使用的算法之一。
此算法在OI界具有极高的人气,据说能解决一切区间处理问题,当然我这种蒟蒻却只能板子题做做,让我们通过下面的题目简单了解一下莫队算法。
题意简述
有 n 个物品,分属于不同的类别,给出m个区间,求在各个区间中连续两次取出相同类别的物品的概率,最简分数表示,若概率为0则输出0/1。(n,m<=50000)
思路
首先,我们需要两个指针 l 和 r 来指示当前区间的位置,用 sum[ ] 数组存放当前区间各类别数量,ans 为区间结果,ans 的分母是所有的组合数 (r - l + 1) (r - l),而分子是各个类别的sum[ ]的平方的累加和,根据其中任意一个区间的 ans 求出相邻区间的 ans。
这里相邻区间定义为当前区间的 l - 1 或 l + 1 或 r - 1 或 r + 1
以 l + 1 为例,如下图:
我们将 l + 1,此时 sum[green] - 1,区间总数也 - 1,这时你会发现改变一次的时间复杂度竟然是O( 1 )?!
其他的改变也是同理
当然这样是远远不够的,若是逐个区间暴力枚举,复杂度是O( n ^ 2 ),太高了呀
这时需要引入变量 unit = sqrt( n ),用它来进行分块(将 n 分为 sqrt( n ) 个区域),并用 ad[ i ] 来存储 i 所在的区间,这样,进行指针跳动时,最多只需要 2 * sqrt( n ) 次就能到达目标,大大优于之前的 n 次。
最后再次致敬莫涛大神!!
代码
1 |
|