树状数组 基本 c++

1.好处:时间复杂度为nlogn,效率更优。
//学就对了//

长这样 (c数组就是树状数组)

image

2.lowbit(灵魂)
含义:取出 x 的二进制里最右边的1后面所有的0
x=6 (110) ⇒ lowbit(6)=2——————//2的1次方
x=8 (1000) ⇒ lowbit(8)=8——————//2的3次方
x=4 (100) ⇒ lowbit(4)=4————————//2的2次方

代码:


int lowbit(int x)
{
  return x & -x;
}

3.两个基础操作:
① add(x,val) 单点加val
② query(x) a[n]~a[m]的前缀和

①、不断往父节点更新,x += lowbit(x) 直到 x>n停止。


void add(int x, int val)
{
  for (;x<=n; x += lowbit(x))
  {
    tr[x] += val;
  }
}

②:向下累加,不断去掉最低位1,<x-= lowbit(x)> 直到x=n停止。
未命名绘图
//图中啊a[1]到a[6]直接用tr[4]+tr[6]就行。

代码实现


int query(int n,int m) 
{
  int res=0;
  for (;x>=n-1; x -= lowbit(x))
  {
    res += tr[x];
  }
  return res;
}
 

完整代码

#include<bits/stdc++.h>
using namespace std;

int n;
int tr[MAXN];

int lowbit(int x)
{
    return x & -x;
}

void add(int x, int val)
{
    for (; x <= n; x += lowbit(x))
        tr[x] += val;
}

int query(int x)
{
    int res = 0;
    for (; x > 0; x -= lowbit(x))
        res += tr[x];
    return res;
}

// 查询区间 [l, r] 的和
int range_query(int l, int r)
{
    return query(r) - query(l - 1);
}

int main()
{
    int n, m;
    cin >> n >> m;
    for (int i = 1; i <= n; i++)
    {
        int v;
        cin >> v;
        add(i, v);
    }
    while(m--)
    {
        int op;
        cin >> op;
        if(op == 1) // 单点加
        {
            int pos, val;
            cin >> pos >> val;
            add(pos, val);
        }
        else
        {
            int l, r;
            cin >> l >> r;
            cout << range_query(l, r) << '\n';
        }
    }
    return 0;
}

结束qwq

posted @ 2026-09-09 18:48  Hina_LZQ  阅读(3)  评论(0)    收藏  举报