当前位置: 首页 > news >正文

浅谈树状数组算法

Part 1 【模版】树状数组 1

  • 例题:P3374

题目大意

单点修改,区间查询。

暴力 1

直接模拟题意,时间复杂度 O ( N M ) O(NM) O(NM)

时间复杂度瓶颈:查询操作。

暴力 2

直接维护前缀和,时间复杂度 O ( N M ) O(NM) O(NM)

时间复杂度瓶颈:修改操作。

铺垫

考虑这个问题:求十个数使得它们中选取几个数的和可以表示 1 1 1 512 512 512 之中的任何一个数。

有一种合法的答案是: 1 , 2 , 4 , 8 , 16 , 32 , 64 , 128 , 256 , 512 1,2,4,8,16,32,64,128,256,512 1,2,4,8,16,32,64,128,256,512。可以观察到这和二进制有很大关系。

多重背包的二进制优化也利用了上述特征,我们能否把它应用到这道题里?可以。

正解思路

考虑在暴力 2 的基础上二进制维护,需要维护使得 s x s_x sx s n s_n sn 增加 k k k,每一次跨度是 i i i 的二进制拆分中最低的一个非零位的位权,简称 lowbit ⁡ ( i ) \operatorname{lowbit}(i) lowbit(i)。所以每一次维护时间复杂度是 O ( log ⁡ N ) O(\log N) O(logN)

查询操作我们也要利用二进制完成,查询 s y s_y sy s x − 1 s_{x-1} sx1 的值,我们需要从后往前枚举,跨度仍然是 lowbit ⁡ ( i ) \operatorname{lowbit}(i) lowbit(i),复杂度 O ( log ⁡ N ) O(\log N) O(logN)

总复杂度 O ( M ⋅ log ⁡ N ) O(M\cdot \log N) O(MlogN)

Part 2 【模版】树状数组 2

  • 例题:P3368

题目大意

区间修改,单点查询。

暴力 1

直接模拟题意,时间复杂度 O ( N M ) O(NM) O(NM)

时间复杂度瓶颈:修改操作。

暴力 2

直接维护差分,时间复杂度 O ( N M ) O(NM) O(NM)

时间复杂度瓶颈:查询操作。

正解思路

注意观察暴力 2,可以转化为上一题,然后利用二进制优化,总时间复杂度也是 O ( M ⋅ log ⁡ N ) O(M\cdot \log N) O(MlogN)

Part 3 【模版】线段树 1

  • 例题:P3372

题目大意

区间修改,区间查询。

暴力思路

模仿第一题思路,如果不考虑时间复杂度就是维护一个前缀和,再维护这个前缀和数组的前缀和,但是时间复杂度是无法承受的。

铺垫

考虑这个数组: 2 , 3 , 1 , 4 , 5 2,3,1,4,5 2,3,1,4,5,我们来求一求它的前缀和以及前缀和的前缀和。

下标 i i i12345
原数 a i a_i ai23145
前缀和 s i s_i si2561015
前缀和的前缀和 s s i ss_i ssi27132338

可以发现, s s i ss_i ssi 的值相当于 a i a_i ai 的加权前缀和。

正解思路

b i b_i bi 表示第 i i i 个数被修改的情况。

式子: s s i = ∑ 1 i a j + ∑ 1 i b j ⋅ ( i + 1 ) + ∑ 1 i b j ⋅ j ss_i=\sum_1^ia_j+\sum_1^ib_j\cdot(i+1)+\sum_1^ib_j\cdot j ssi=1iaj+1ibj(i+1)+1ibjj

发现我们只需要维护一下原数组的前缀和、修改值的前缀和、修改值的加权前缀和。复杂度同上。

Part 4 逆序对

  • 例题:P1908

声明

本题可以使用归并排序,下面介绍一种树状数组的做法。

思路

不妨考虑桶维护。首先对原数组进行离散化,然后正序枚举,计算前面有多少个数比当前数大。这是一个求前缀和的过程,可以用树状数组维护。

总结

树状数组很好用,可以将 O ( N ) O(N) O(N) 的时间复杂度优化到 O ( log ⁡ N ) O(\log N) O(logN)

相关文章:

  • Type_ C和锂电池自切换电路
  • 圣奥获“突出贡献企业”和“强工业企业”等多项殊荣
  • 【Git】--- 初识Git Git基本操作
  • BaseActivity 和 BaseFragment 的现代化架构:ViewBinding 与 ViewModel 的深度整合
  • leetcode hot100特殊题型
  • 安装配置Anaconda
  • 前缀和算法第一弹(一维前缀和和二维前缀和)
  • c++图论(三)之图的遍历
  • 图解多头注意力机制:维度变化一镜到底
  • doris:安全概览
  • 【计算机视觉】工业表计读数(1)--基于关键点检测的读数识别方案
  • uboot源码结构
  • 树莓派 连接 PlutoSDR 教程
  • 给AI编程泼一盆冷水
  • 了解浏览器
  • [C语言]数据在内存中的存储
  • 二叉树的基本操作与实现:C语言深度剖析
  • Leetcode-回溯-子集型
  • 增量数据同步怎么做
  • Show、Hide和Setvisible的区别
  • 五大光伏龙头一季度亏损超80亿元,行业冬天难言结束
  • 国家网信办举办在欧中资企业座谈会,就数据跨境流动等进行交流
  • 上海科创再出发:“造星”的城和“摘星”的人
  • 澎湃回声丨23岁小伙“被精神病8年”续:今日将被移出“重精”管理系统
  • 十四届全国人大常委会第十五次会议在京闭幕
  • 石家庄:城市更新,生活向美