莫队算法小结

本文总结了莫队算法的基本思想和应用场景,包括如何将区间查询转化为O(1)复杂度的转移操作,并通过实例解释了莫队算法在解决区间问题上的应用,如小Z的袜子问题和树上莫队算法,讨论了树上莫队如何处理非连续区间询问,以及面对有修改情况的处理策略。
摘要由CSDN通过智能技术生成

wtf,最近挖坑有点小多啊,没办法>_<容我先把糖果公园A了再来写这个吧= =看看今天能不能A掉

好吧,我承认我第二天才把糖果公园A掉>_<下面把这篇小结补上

首先众所周知的是莫队算法是要把询问先按左端点属于的块排序,再按右端点排序

复杂度就先不证了,有兴趣的同学可以自己YY下或者查阅资料

下面举几个例子详细说明


1.小Z的袜子

Description:

给定一个序列 m 个询问

每次询问:

区间中选两个数,两个数相等的概率

若概率为0则输出 01

仔细观察发现,令 x 表示x这个值出现的次数,则每次询问 [l,r] 区间时答案就是

(x2)(rl+12)

假如我们知道 [l,r] 区间中每个x出现的次数,用 cntx 表示,用ans表示当前答案

那么我们可以考虑当我们从 [l,r] 变为 [l,r+1] 时对ans的影响

已知只有 ar 这个值的变化影响着我们的答案,而且容易看出答案是

ans=anscntar(cntar1)

cntar=cntar+1

ans=ans+cntar(cntar1)

想一想为什么

其他情况同理请自行思考

这样每次转移均是 O(1) ,总复杂度 O(n1.5)

Code

2.Codeforces 86D(Yandex.Algorithm 2011)

几乎和小Z的袜子一模一样的莫队模板题

Code

3.bzoj 3289(Mato的文件管理)

Description

给定一个序列 m 个询问

每次询问:

区间中逆序对数

很显然的发现可以用树状数组+莫队艹过去,每次修改是O(nlogn)的,可以通过

Code

这些题基本上都是一个套路了,学了莫队基本就会了

因为每次查询都是一个连续的区间,我们可以轻易找到每移动一次后对答案的贡献

那么,如果不是正常的对序列的区间询问,而是对树上两点路径的询问该怎么办呢?

没错,这就是传说中的。。。

树上莫队

先举个例子

1.Spoj 10707 Count on a tree II(COT2)

Description

给定一棵树上n个结点上的数值, m 个询问

每次询问:

区间中不同值的个数

卧槽,这TM怎么做啊?区间不是连续的啊!这莫队是不是做不了啊?

莫慌,我们有个神奇的东西,叫做

dfs序

我们可以用时间戳来对每个节点进行标记,$l_x$,$r_x$分别表示$x$的进出时间

我们利用了dfs序的性质,可以把两点间路径转换为一个连续的区间(还需要考虑Lca的问题,想一想,为什么)

没错,这样我们便可以对dfs序进行分块,莫队一样搞!

神犇们看到现在的话应该会做了,蒟蒻还是继续详细的说做法把>_<

定义S(u,v) uv 路径上的顶点集合,root表示根节点

S(u,v)=S(root,u)S(root,v)lca(u,v) ( 表示集合中的对称差)

定义 T(u,v)=S(root,u)S(root,v) ,我们先不管lca的事情

如果我们从 uv 的路径变成 uv 的路径的话对答案有什么影响呢?

根据定义我们可以得到 T(u,v)=S(root,u)S(root,v)

T(u,v)T(u,v)=S(root,u)S(root,v)S(root,u)S(root,v)

=S(root,v)S(root,v)

=T(v,v)

于是我们可以得到 T(u,v)=T(u,v)T(v,v)

即每次更新时 T(v,v) 即可

也即对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=n23,分为 n13

相当于询问分成了 nB2 块,每次移动距离为 B ,每块最多移动n

由于n和q同阶,所以总复杂度是 O(nB+nnB2) 所以得到 B=n23 最优

然后就是拍代码啦~

Code

完结撒花!

(妈蛋从10点多写到现在总算是写完了,感人肺腑,意识不清可能哪里写错了,多多包涵>_<

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值