这篇博客相当于线段树学习博客的补充。
原文链接:2021-07-27 重见线段树
一、双tag线段树
这种时候,如果不做特殊处理,tag添加的顺序将影响最终结果,十分麻烦。
由于操作含有乘法和加法,并且先乘后加与先加后乘结果不同。所以标记下传的时候要这样处理:
void pushdown(int u){
//先乘后加,并下传懒标记
tr[u<<1].sum=(tr[u<<1].sum*tr[u].mu)%p;
tr[u<<1].sum=(tr[u<<1].sum+(tr[u<<1].r-tr[u<<1].l+1)*tr[u].ad)%p;
tr[u<<1].ad=(tr[u].ad+tr[u<<1].ad*tr[u].mu)%p;//子节点需要ad标记的更新与父节点的mu有关
tr[u<<1].mu=(tr[u<<1].mu*tr[u].mu)%p;
tr[u<<1|1].sum=(tr[u<<1|1].sum*tr[u].mu)%p;
tr[u<<1|1].sum=(tr[u<<1|1].sum+(tr[u<<1|1].r-tr[u<<1|1].l+1)*tr[u].ad)%p;
tr[u<<1|1].ad=(tr[u].ad+tr[u<<1|1].ad*tr[u].mu)%p;
tr[u<<1|1].mu=(tr[u<<1|1].mu*tr[u].mu)%p;
//父节点懒标记回归默认
tr[u].ad=0;
tr[u].mu=1;
}
void modify1(int u,ll l,ll r,ll k){
//区间*k
if(tr[u].l>=l&&tr[u].r<=r){
tr[u].sum=(tr[u].sum*k)%p;
tr[u].ad=(tr[u].ad*k)%