莫队小结
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了莫队小结相关的知识,希望对你有一定的参考价值。
最近刚刚学习了莫队算法,感觉很神奇,很强大,于是我打算写一些小小的总结,希望能对看的人有一点点帮助。ps:noip前我是不会学新算法啦qwq...老师让我多刷刷题连连代码能力
对于莫队算法,我们可以简单的将其分为几类,普通莫队,带修莫队,树上莫队(应该没别的了吧qwq我只会这三个)。
概述:莫队算法是用于解决什么问题呢?
给出莫队应用范围:对于一个序列在已知f[l,r]的情况下可以O1或者Ologn的复杂度求出f[l,r+1],f[l,r-1],f[l+1,r],f[l-1,r],并且题目不强制在线,那么我们就可以用莫队算法给出一个满意的复杂度。
那莫队的整体思想是什么呢?
其实是将题目中所给的询问记录下来,然后通过某种排序,使他们询问顺序发生改变,然后通过暴力移动左右两个边界(l,r)来处理处每一个询问的值,而如何排序,就需要用到一点分块的思想,来将其最坏情况复杂度变为n根号n。
一、普通莫队
这里先给出例题和代码,以及思路,后面将会给出详细的证明。
举个简单的例子,我现在有若干个物品,每一个物品对应一个颜色,给出若干个询问,请你给出对于每一个询问区间,它里面有多少种颜色。
[SDOI2009]HH的项链
这是一道可以用莫队解决的题目中最简单的一道了吧,他们好像都是用树状数组搞得,我也没往那想,单纯为了练莫队。
先贴上代码
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,a[50005],m,pos[50005],f[50005],ans; 4 struct Ques{ 5 int l,r,ans,id; 6 bool operator < (const Ques &o)const{ 7 if(pos[l]!=pos[o.l])return pos[l]<pos[o.l]; 8 return r<o.r; 9 } 10 }q[50005]; 11 bool cmp(Ques x,Ques y){ 12 return x.id<y.id; 13 } 14 int main() 15 { 16 // freopen("1.txt","r",stdin); 17 scanf("%d",&n); 18 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 19 scanf("%d",&m); 20 for(int i=1;i<=m;i++){ 21 scanf("%d%d",&q[i].l,&q[i].r); 22 q[i].id=i; 23 } 24 int len=sqrt(n)+1; 25 for(int i=1;i<=n;i++)pos[i]=(i-1)/len+1; 26 sort(q+1,q+m+1); 27 int l=1,r=0; 28 for(int i=1;i<=m;i++){ 29 while(r<q[i].r){ 30 r++; 31 f[a[r]]++; 32 if(f[a[r]]==1)ans++; 33 } 34 while(r>q[i].r){ 35 f[a[r]]--; 36 if(!f[a[r]])ans--; 37 r--; 38 } 39 while(l>q[i].l){ 40 l--; 41 f[a[l]]++; 42 if(f[a[l]]==1)ans++; 43 } 44 while(l<q[i].l){ 45 f[a[l]]--; 46 if(!f[a[l]])ans--; 47 l++; 48 } 49 q[i].ans=ans; 50 } 51 sort(q+1,q+m+1,cmp); 52 for(int i=1;i<=m;i++)printf("%d\n",q[i].ans); 53 return 0; 54 }
对于这道题,我们的思路是什么呢?先想一想最暴力的算法如何解决,对于每一次询问,我们从l枚举到r,并记录颜色数量,这样复杂度最坏情况下是n2的,显然不能令人满意,但如果我们可以将其将为n根号n,那么他就可以被完美的解决。
我们可以发现这道题是满足莫队的应用范围的,因为如果我知道l到r的颜色总数,那么我可以在o1的时间内求出[l,r+1]....等等,(放学啦...未完待续)
以上是关于莫队小结的主要内容,如果未能解决你的问题,请参考以下文章