树状数组+求逆序对

本文介绍了树状数组在动态求连续区间和及逆序对问题中的应用,详细阐述了树状数组的工作原理和操作过程,并提供了相关算法的解释和实例分析。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

1.动态求连续区间和  

2,逆序对

2.小朋友排队


右图圆圈中标记有数字的结点,存储的是称为树状数组的 tree[]tree[]。一个结点上的 tree[]tree[]的值,就是它树下的直连的子结点的和。例如:

  • tree[1]=a1​
  • tree[2]=tree[1]+a2​
  • tree[3]=a3​
  • tree[4]=tree[2]+tree[3]+a4​
  • tree[8]=tree[4]+tree[6]+tree[7]+a8​

而我们利用 tree[],有效地完成下面两个操作:

  1. 查询,即求前缀和 sum,例如:

    • sum(8)=tree[8]
    • sum(7)=tree[7]+tree[6]+tree[4]
    • sum(6)=tree[6]+tree[4]

    右图中的虚线箭头是计算 sum(7) 的过程。显然,计算的复杂度是 O(logn) 的,这样就达到了快速计算前缀和的目的。

  2. 维护。tree[] 本身的维护也是高效的。当元素 a 发生改变时,能以 O(logn)的高效率修改tree[] 的值。例如更新了 a3​,那么只需要修改 tree[3]、tree[4]、tree[8]⋯,即修改它和它上面的那些结点:父结点以及父结点的父结点。

  1. 查询的过程,是每次去掉二进制的最后的 1。例如求 sum(7) = tree[7] + tree[6] + tree[4],步骤是:
    • 7 的二进制是111,去掉最后的 1,得 110,即 tree[6];
    • 去掉 6 的二进制 110 的最后一个 1,得 100,即tree[4];
    • 4 的二进制是 100,去掉 1 之后就没有了。
  2. 维护的过程,是每次在二进制的最后的 1 上加 1。例如更新了a3​,需要修改tree[3]、tree[4]、tree[8]⋯ 等等,步骤是:
    • 3 的二进制是 11,在最后的 1 上加上 1 得100 ,即 4 ,修改 tree[4];
    • 4 的二进制是 100,在最后的 1 上加 1,得 1000,即 8,修改 tree[8];
    • 继续修改 tree[16]、tree[32]⋯ 等等。

“去掉二进制的最后的 1”、“在二进制的最后的 1

lowbit(x) = x & -x 的功能是找到 x 的二进制数的最后一个 1。其原理是利用了负数的补码表示,补码是原码取反加一。例如

  • x = 6 = 00000110_2
  • -x = x补 = 11111010_2
  • 得 lowbit(x) = x & -x =10_2

1.动态求连续区间和  

给定 n 个数组成的一个数列,规定有两种操作,一是修改某个元素,二是求子数列 [a,b][a,b] 的连续和。

输入格式

第一行

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值