zoukankan      html  css  js  c++  java
  • 进阶线段树之乘法操作

    毒瘤梅开二度

    写在前面

    如果你还不了解什么是线段树 或者你只是简单了解但是并不知道工作原理以及基本操作 请你不要观看这篇博客(如果执意观看可能会引起您的部分不适
    在看这篇博客之前可以先看一下 线段树(毒瘤)总结

    下面让我们步入正题

    我们在前面已经介绍过线段树基本操作(单点修改 单点查询 区间修改 区间求值)
    但是都是简单的加减运算 如果我们需要乘法运算呢?

    • 如果只是简单的乘法运算 那依然很简单 直接让lazy标记乘几就好了 后面pushdown的时候将乘法标记下放 然后t[root].sum *= lazy就好了
    • 但是如果既有乘又有加呢? 我们需要考虑是先乘还是先加 因为存在优先级这个东西(乘法比加法高 括号比乘法高)
    • 所以我们将lazy标记改进一下 改进为记录乘法的laz 和 记录加法的add 两个懒惰标记
    • 在想要进行乘法运算的时候很简单 直接pushdown的时候t[root].sum *= laz就好了 但是在进行加法运算的时候 我们需要将原来的add * lazy 再加上add
    • 解释一下原因:
      原来的add 是在当前操作之前进行的 所以优先级应该高于当前add 就像是(a[i]+5)4+6 加5的操作是之前进行的 进行之后再乘4 会将之前的+5一起乘 而后面的+6是当前操作 因此不需要lazy 其他操作大体和加减一样

    代码实现

    //在做乘法线段树的时候一定要注意取模  一般情况下都会炸int
    (如果感觉时间会被卡可以将*2的操作改为<<1 , +1改为|1)
    void pushdown(ll p){
    	t[p*2].sum = (ll)(t[p].laz * t[p*2].sum + ((t[p*2].r - t[p*2].l + 1)*t[p].add)%mod)%mod;
    	t[p*2+1].sum = (ll)(t[p].laz * t[p*2+1].sum + (t[p].add * (t[p*2+1].r - t[p*2 + 1].l + 1))%mod)%mod;
    	
    	t[p*2].laz = (ll)(t[p*2].laz * t[p].laz)%mod;
    	t[p*2+1].laz = (ll)(t[p*2+1].laz * t[p].laz)%mod;
    	
    	t[p*2].add = (ll)(t[p*2].add*t[p].laz + t[p].add)%mod;
    	t[p*2+1].add = (ll)(t[p*2+1].add * t[p].laz + t[p].add) % mod;
    	
    	t[p].laz = 1,t[p].add = 0;
    }
    
    如初见 与初见
  • 相关阅读:
    深入理解npm run命令,run命令的两条潜规则
    oracle 删除表空间及数据文件方法
    Oracle11g创建表空间和用户,并授权
    java poi 读取excel 获取第一个不隐藏的sheet
    VBS 学习
    VBS 操作Excel
    Selenium + Python操作IE 速度很慢的解决办法
    Selenium打开IE报错“Protected Mode settings...”解决方法
    Robot Framework搭建
    获取一组元素的最后一个
  • 原文地址:https://www.cnblogs.com/HISKrrr/p/13228664.html
Copyright © 2011-2022 走看看