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;
    }
    
    如初见 与初见
  • 相关阅读:
    点击导航栏,实现下方内容改变
    简述23种软件设计模式
    MyFirstServlet学习笔记
    淘宝网---6个质量属性
    架构漫谈阅读感悟一
    大型网站技术架构:核心原理与案例分析阅读笔记二
    软件体系结构师工作流程
    大型网站技术架构:核心原理与案例分析阅读笔记一
    软件需求分析教程阅读笔记四
    软件需求分析教程阅读笔记三
  • 原文地址:https://www.cnblogs.com/HISKrrr/p/13228664.html
Copyright © 2011-2022 走看看