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;
}