普通莫队算法

普通是用来离线查询一段区间里面的答案
莫队算法由莫涛发明,一般分为两类,一是莫队维护区间答案,二是维护区间内的数据结构。当然也有树上莫队,带修改莫队、二维莫队等等。这篇文章主要介绍的是普通莫队算法。
如果我们碰到一个问题,在[1-n]的区间内,有很多l,r需要查询,这时候我们就可以用莫队来写。
比如说,我们遇到一个问题,有一个序列,要求在这个序列[l,r]区间内的不同的所有不同数各自的个数,当l,r很多的时候,我们就可以用莫队来做。
首先就是莫队的基础,就是一个个处理询问
我们先模拟一下这个过程
ql和qr就是莫队的两个搜索指针,而l和r这个区间就是我们要去的区间
我们定义cnt1为[ql,qr]中有多少个1;
我们定义cnt2为[ql,qr]中有多少个2;
我们定义cnt3为[ql,qr]中有多少个3;
请添加图片描述
然后我们把qr往右挪一下,可以发现cnt3++

请添加图片描述
同理,将ql和qr各往右挪一格,此时cnt1–,cnt2++

请添加图片描述
操作的代码如下

inline void add(int x){
   
    cnt[x]++;
    if(cnt[x]==1)ans++;
}

inline void del(int x){
   
    cnt[x]--;
    if(cnt[x]==0)ans--;
}

//在获取答案时:
while(l>q[i].l) add(a[--l]);
while(r<q[i].r) add(a[++r]);
while(l<q[i].l) del(a[l++]);
while(r>q[i].r) del(a[r--]);

由此可以分析,每次挪动的时间复杂度是O(1),有m个询问,最坏的情况下复杂度是O(nm)。
普通莫队算法就是让这个挪动尽可能的少,第一步是强行离线,把所有的询问存下来,然后按左端点排序,但是这样的话最坏的情况还是有可能是O(nm)复杂度,所以我们用到了分块思想,我们把序列分为根号n个长度为根号n的块,若左端点在同一个块内,则按右端点排序,这样的话时间复杂度可以降到n根号n

排序代码

bool cmp(query a,query b){
   
return (a.r/block)==(b.r/block)?a.l<b
  • 3
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值