莫队总结
莫队:有人靠推理,有人靠玄学。
莫队
莫队算法可以解决一类离线区间询问问题,适用性极为广泛。同时将其加以扩展,便能轻松处理树上路径询问以及支持修改操作。 -----OI wiki
莫队是一种离线做法,其的基础的是分块。
普通莫队
我们首先进行分块操作,在进行普通莫队时,块长要取 \(\sqrt n\) 时间复杂度最优,为 \(O(n^\frac{3}{2})\)。
莫队所经行的操作是把所询问的区间按照左端点所在的块从小到大为第一关键字,以右端点从小到大为第二关键字排序,然后设置已个当前求解的区间 \(L,R\),去让其每次询问移动至所询问区间,如果能够 \(O(1)\) 转移,并在求解过程中维护答案。
其复杂度证明:
对于每一块而言,最坏情况下询问的右端点都会从 \(1\) 至 \(n\),为 \(O(n*(n/s)),s\) 为块长,左端点移动为 \(O(s\times m)\),在 \(n,m\) 同阶情况下,总复杂度为 \(O(n(n/s+s)) \geq O(n \sqrt{n} )\) 当且仅当 \(s=n/s\) 时即 \(s=\sqrt{n}\) 时,等号成立。
莫队的核心流程如下:
for(int i=1;i<=m;i++){
while(L<quest[i].l){
L++;
del(L-1,-1);
}
while(L>quest[i].l){
L--;
add(L,1);
}
while(R<quest[i].r){
R++;
add(R,1);
}
while(R>quest[i].r){
R--;
del(R+1,-1);
}
ans[quest[i].id]=num;
}
其中,quest 为询问,l,r,id 记录其左右端点与编号。
例题:【SDOI2009】HH的项链
按块长为 \(O(\sqrt {n})\) 分块,莫队直接做,转移有:
void add(int p,int v){
tong[a[p]]+=v;
if(tong[a[p]]==1){
num++;
}
}
void del(int p,int v){
tong[a[p]]+=v;
if(tong[a[p]]==0){
num--;
}
}

浙公网安备 33010602011771号