线段树(加法与乘法的lazy标记)

struct Node{int l,r,add,mul;}tree[N];

开始在想,加了又乘又加,乘法又优先,怎么搞

现在先理清几点

1.add,mul是指现在算了,儿子没算的

2.mul只记儿子要乘的,如果先加在乘,直接把add*val就行了

举个例子

一个区间

1 4 3 2   全部 +1 , *2 ,+1

首先 tree[1].add+=1,mul不变

其次 tree[1].mul*=2,tree[1].add*=2

再其次 tree[1].add+=1

查询1--2 就是tree[2].sum*tree[1].mul+tree[1].add*(r-l+1)==5*2+3*2=16

其实,加上来在乘的在add里面

 代码

inline void init(int o){
	tree[o].val%=p,tree[o].add%=p,tree[o].mul%=p;
}
void build(LL o,LL l,LL r){
	tree[o].l=l,tree[o].r=r;
	if(l==r){tree[o].val=a[l];return;}
	LL mid=(l+r)>>1;
	build(o<<1,l,mid),build(o<<1|1,mid+1,r);
	tree[o].val=tree[o<<1].val+tree[o<<1|1].val;
}
void spread(LL o){
	LL mul=tree[o].mul,add=tree[o].add;
	tree[o<<1].val=tree[o<<1].val*mul+add*(tree[o<<1].r-tree[o<<1].l+1);
	tree[o<<1|1].val=tree[o<<1|1].val*mul+add*(tree[o<<1|1].r-tree[o<<1|1].l+1);
	tree[o<<1].mul*=mul,tree[o<<1|1].mul*=mul;
	tree[o<<1].add=(tree[o<<1].add*mul+add)%p;
	tree[o<<1|1].add=(tree[o<<1|1].add*mul+add)%p;
	tree[o].mul=1,tree[o].add=0;
	init(o<<1),init(o<<1|1);
}
void update(LL o,LL op,LL l,LL r,LL k){
	if(l<=tree[o].l&&tree[o].r<=r){
		if(op==1){
			tree[o].val*=k;
			tree[o].mul*=k;
			tree[o].add*=k; 
		}
		else{
			tree[o].val+=(tree[o].r-tree[o].l+1)*k;
			tree[o].add+=k;
		}
		return;
	}
	if(tree[o].mul!=1||tree[o].add) spread(o);
	LL mid=(tree[o].l+tree[o].r)>>1;
	if(mid>=l) update(o<<1,op,l,r,k);
	if(mid<r) update(o<<1|1,op,l,r,k);
	tree[o].val=tree[o<<1].val+tree[o<<1|1].val;
	init(o);
}
LL quary(LL o,LL l,LL r){
	if(l<=tree[o].l&&tree[o].r<=r) return tree[o].val;
	if(tree[o].mul!=1||tree[o].add) spread(o);
	LL mid=(tree[o].l+tree[o].r)>>1,cur=0;
	if(mid>=l) cur+=quary(o<<1,l,r);
	if(mid<r) cur+=quary(o<<1|1,l,r);
	return cur;
}

 

  • 3
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

FSYo

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

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

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

打赏作者

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

抵扣说明:

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

余额充值