莫队算法 (普通莫队、带修莫队、树上莫队)

本文详细介绍了莫队算法,包括普通莫队、带修莫队和树上莫队。普通莫队通过分块、排序和指针优化实现高效求解;带修莫队在修改操作后维护查询答案;树上莫队结合欧拉序和LCA函数实现树形结构的查询。文章包含例题代码和练习题,适合进阶学习。
摘要由CSDN通过智能技术生成

莫队算法

主要基于分块的思想

询问区间
结构体记录询问的左右端点及询问编号 (这是一个离线算法)
通过排序优化指针扫描顺序优化时间复杂度 。

1.普通莫队

例题:SP3267 DQUERY - D-query.

一、分块 :
    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;
}
</
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值