洛谷 P3373 【模板】线段树 2

本文通过解决P3373题目,深入探讨线段树的lazy标记更新策略,特别是如何优雅地处理加法与乘法操作,实现高效的区间更新与查询。作者分享了从XTYF_CKY博客中学习到的技巧,即通过转换乘法和加法运算,确保两者不会互相影响,从而提升线段树的性能。

P3373

思路学习于:XTYF_CKY 的博客

看了这个线段树裸题,竟然一时半会写不出,果然线段树水平还是太菜太菜了,学习了上面这位大佬后,让我对lazy更新有了新的认识,之前我自己手写lazy时,也想到了查询的时候也要标记传递,但终归水平太菜,没有完善出来,这个题呢,又有加法又有乘法,但是我可以把乘法和加法处理一下,使得乘法可以优先,比如(2+x)*2我可以转化成2*x+4,这样就可以无所畏惧的同时处理这两个lazy标记而不用担心他们互相影响了。

#include<cstdio>
using namespace std;
typedef long long ll;
const int maxn=1e5+10;
ll sum[maxn*4],add[maxn*4],mul[maxn*4],mod,v;
void pushdown(int o,int ls,int rs,int l,int m,int r)
{
	if(l==r||(add[o]==0&&mul[o]==1))return;
	add[ls]=(add[ls]*mul[o]+add[o])%mod;
	add[rs]=(add[rs]*mul[o]+add[o])%mod;
	mul[ls]=mul[ls]*mul[o]%mod;
	mul[rs]=mul[rs]*mul[o]%mod;
	sum[ls]=(sum[ls]*mul[o]+add[o]*(m-l+1))%mod;
	sum[rs]=(sum[rs]*mul[o]+add[o]*(r-m))%mod;
	add[o]=0,mul[o]=1;
}
void up(int o,int l,int r,int ql,int qr,int op)
{
	int m=(l+r)/2,ls=o*2,rs=o*2+1;
	pushdown(o,ls,rs,l,m,r);
	if(l>=ql&&r<=qr)
	{
		if(op==1)
		{
			mul[o]=v;
			sum[o]=sum[o]*v%mod;
		}
		else
		{
			add[o]=v;
			sum[o]=(sum[o]+v*(r-l+1))%mod;
		}
		return;
	}
	if(ql<=m)up(ls,l,m,ql,qr,op);
	if(qr>m)up(rs,m+1,r,ql,qr,op);
	sum[o]=(sum[ls]+sum[rs])%mod;
}
ll qu(int o,int l,int r,int ql,int qr)
{
	int m=(l+r)/2,ls=o*2,rs=o*2+1;
	pushdown(o,ls,rs,l,m,r);
	if(l>=ql&&r<=qr)return sum[o];
	ll res=0;
	if(ql<=m)res+=qu(ls,l,m,ql,qr);
	if(qr>m)res+=qu(rs,m+1,r,ql,qr);
	return res%mod;	
}
int main()
{
	int n,q,x,y,op;
	scanf("%d%d%lld",&n,&q,&mod);
	for(int i=1;i<=n*4;i++)mul[i]=1;
	for(int i=1;i<=n;i++)
	{
		scanf("%lld",&v);
		up(1,1,n,i,i,2);
	}
	while(q--)
	{
		scanf("%d%d%d",&op,&x,&y);
		if(op!=3)
		{
			scanf("%lld",&v);
			up(1,1,n,x,y,op);
		}
		else printf("%lld\n",qu(1,1,n,x,y));
	}
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

长沙橘子猫

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值