zoukankan      html  css  js  c++  java
  • 用矩阵表示变化&&线段树维护矩阵

    用矩阵表示变化&&线段树维护矩阵

    引入问题

    • 已知一个数列
    • 进行下面四种操作
    • 1.区间赋值成 (x)
    • 2.区间乘上一个数 (x)
    • 3.区间加上一个数 (x)
    • 4.求出区间每一个数的和

    洛谷P3373 (只有后面三种操作)

    矩阵入门

    可以看看我写的这篇博客

    正文

    线段树维护的是带有结合律的东西

    假如维护的东西不存在结合律

    那么每次一个新的标记就会把旧的标记挤下去

    每一个标记都要遍历整棵树,复杂度变成 (O(nm))

    线段树维护矩阵

    众所周知,矩阵乘法是有结合率

    即 :

    (A(B C) = (AB)C)

    那么我们可以在线段树的每一个节点维护一个矩阵来表示一些信息

    那么我们的每一次操作都想方设法把它变成"乘上一个矩阵"

    那么我们就可以线段树维护区间矩阵乘法,来表示一些结合律不是那么明显的信息

    注意 : 由于矩阵乘法不具有交换律,所以我们每次只能左乘,或只能右乘一个转移矩阵

    左乘右乘 分别看个人实现的是一个列矩阵,还是一个行矩阵

    矩阵模拟变化

    每一个结点用矩阵可以表示成这样

    [left[egin{array}{c}v\send{array} ight] ]

    (v) 表示维护的权值(区间和),(s) 表示结点的大小


    来按题目中的意思模拟

    把原矩阵左乘一个矩阵来得到我们要的新矩阵

    区间加 (x)

    [left[egin{array}{c}1&x\0&1end{array} ight] imesleft[egin{array}{c}v\send{array} ight]=left[egin{array}{c}v + s imes x\send{array} ight] ]

    区间乘 (x)

    [left[egin{array}{c}x&0\0&1end{array} ight] imesleft[egin{array}{c}v\send{array} ight]=left[egin{array}{c}v imes x\send{array} ight] ]

    区间赋值为 x

    [left[egin{array}{c}0&x\0&1end{array} ight] imesleft[egin{array}{c}v\send{array} ight]=left[egin{array}{c}s imes x\send{array} ight] ]

    区间求和

    即按普通的线段树那样

    把每一个结点的矩阵加在一起即可


    对了,最好写一个矩阵类,弄个矩阵乘法加法之类的

    由于矩阵运算有一个 (8) 的小常数,我吸氧后才勉强通过

    最后放代码

    (color {Deepskyblue} {Code})

  • 相关阅读:
    C语言学习趣事_BT_C_Code_混乱编程代码分析_1
    随想系列_6_终于被我发现Microsoft的一个错误了
    C语言学习趣事_经典面试题系列_2
    C++_系列自学课程_第_2_课_牛刀小试
    PLC_自动化控制系统_1_简说自动化控制系统
    随想系列_5_乱七八糟
    Android Handler使用
    Android Layout 布局属性
    MotionEvent事件在onInterceptTouchEvent()、onTouchEvent()中的传递顺序【转】
    AndroidMenifest 有关SdkVersion 说明
  • 原文地址:https://www.cnblogs.com/Lskkkno1/p/11687044.html
Copyright © 2011-2022 走看看