首页 > 代码库 > 莫队算法小结
莫队算法小结
唔,想有更加舒爽的阅读体验请移步http://mlz000.logdown.com/posts/252433-mo-algorithm-summary
首先众所周知的是莫队算法是要把询问先按左端点属于的块排序,再按右端点排序
复杂度就先不证了,有兴趣的同学可以自己YY下或者查阅资料
下面举几个例子详细说明
1.小Z的袜子
Description:
给定一个序列m询问
每次询问:
区间中选两个数,两个数相等的概率
若概率为则输出0/1
仔细观察发现,令x表示x个值出现的次数,则每次询问[l,r]区间时答案就是
假如我们知道[l,r]区间中每个x出现的次数,用表示,用ans表示当前答案
那么我们可以考虑当我们从[l,r]为[l,r+1]时对ans的影响
已知只有这个值的变化影响着我们的答案,而且容易看出答案是
想一想为什么
其他情况同理请自行思考
这样每次转移均是,总复杂度
Code
2.Codeforces 86D(Yandex.Algorithm 2011)
几乎和小Z的袜子一模一样的莫队模板题
Code
3.bzoj 3289(Mato的文件管理)
Description
给定一个序列m个询问
每次询问:
区间中逆序对数
很显然的发现可以用树状数组+莫队艹过去,每次修改是的,可以通过
Code
这些题基本上都是一个套路了,学了莫队基本就会了
因为每次查询都是一个连续的区间,我们可以轻易找到每移动一次后对答案的贡献
那么,如果不是正常的对序列的区间询问,而是对树上两点路径的询问该怎么办呢?
没错,这就是传说中的。。。
树上莫队
先举个例子
1.Spoj 10707 Count on a tree II(COT2)
Description
给定一棵树上n个结点上的数值,m个询问
每次询问:
区间中不同值的个数
卧槽,这TM怎么做啊?区间不是连续的啊!这莫队是不是做不了啊?
莫慌,我们有个神奇的东西,叫做
dfs序
我们可以用时间戳来对每个节点进行标记,l[u],r[u]分别表示u的进出时间
我们利用了dfs序的性质,可以把两点间路径转换为一个连续的区间(还需要考虑Lca的问题,想一想,为什么)
没错,这样我们便可以对dfs序进行分块,莫队一样搞!
神犇们看到现在的话应该会做了,蒟蒻还是继续详细的说做法把>_<
定义为路径上的顶点集合,root表示根节点
定义,我们先不管lca的事情
如果我们从的路径变成的路径的话对答案有什么影响呢?
根据定义我们可以得到
于是我们可以得到
即每次更新时即可
也即对v-v‘的路径(除了lca(v,v‘))的点的存在性取反即可
实际上我们记录的是T,然后每次改变lca(v,v‘)的存在性将其变为S统计答案
然后再将lca(v,v‘)的存在性还原变回T就行了
其实读者可以换个图把dfs序标一下帮助理解>_<
然后这题实际已经解决了,将dfs序分块就将区间化为dfs序上区间问题,考虑lca就可以了
Code
2.WC 2013 糖果公园(Uoj 58)
Description
唔。。题目太长了童鞋们自己看吧>_<戳这里
总之它是需要修改的啦~
好了,想必看到这里,大家对莫队算法和树上莫队算法都已经有了一定的了解
我们发现之前我们做的题都是只有查询没有修改,那么有修改的就不可以做了吗?
并非如此
如果没有修改我们随意搞搞就可以了,有修改的话相等于加了一个时间的维度变成了三维的
我们可以按左端点为第一关键字,右端点为第二关键字,时间为第三关键字排序
预处理每次修改前的颜色,以及这次修改后的颜色
莫队对询问排序
每次询问发现与上次时间不同时暴力t++,t--同时修改颜色及答案即可(用到之前预处理)
然后解决完时间问题后便就是正常的二维莫队了
如果我们将块的大小设为,分为块
相当于询问分成了块,每次移动距离为B,每块最多移动n
由于n和q同阶,所以总复杂度是,所以得到最优
然后就是拍代码啦~
Code
完结撒花!
(妈蛋从10点多写到现在总算是写完了,感人肺腑,意识不清可能哪里写错了,多多包涵>_<
莫队算法小结
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。