莫队算法
主要基于分块的思想
用结构体记录询问的左右端点及询问编号 (这是一个离线算法)
通过排序优化指针扫描顺序优化时间复杂度 。
1.普通莫队
一、分块 :
n=read();
ll k=sqrt(n);//块的大小允许调整
for(int i=1;i<=n;i++){
a[i]=read();
kuai[i]=(i-1)/k+1;
}
优化1:快读(&快输)
二、 排序(以左端点所在块编号递增)
inline bool cmp1(question &x,question &y){
return (kuai[x.l]^kuai[y.l])?x.l<y.l:(kuai[x.l]&1)?x.r<y.r:x.r>y.r;
}//cmp函数
优化2:奇偶排序 ——对于左端点在同一奇数块的询问区间,右端点升序排列,反之右端点降序。
然后在主函数中cmp函数sort即可 。(该优化只可在普通莫队中使用)
三、莫队:
void deal(){
ll l=1,r=0;
ll ans=0;
for(int i=1;i<=m;i++){//对于排序后的每个询问
while(l>q[i].l) ans+=!cou[a[--l]]++;//cou数组记录出现次数
/*{
l--;
cou[a[l]]++;
if(cou[a[l]]==1) ans++;
}*/
while(r<q[i].r) ans+=!cou[a[++r]]++;
/*{
r++;
cou[a[r]]++;
if(cou[a[r]]==1) ans++;
}*/
while(l<q[i].l) ans-=!--cou[a[l++]];
/*{
cou[a[l]]--;
if(cou[a[l]]==0) ans--;
l++;
}*/
while(r>q[i].r) ans-=!--cou[a[r--]];
/*{
cou[a[r]]--;
if(cou[a[r]]==0) ans--;
r--;
}*/
q[i].ans=ans;
}
return;
}
</