ACM模板——树状数组

树状数组:

一、概念:树状数组(Binary Indexed Trees,简称,BIT)是一种特殊的数据结构,这种数据结构的时空复杂度和线段树相似,但是它的系数要小得多。它可以方便地查询出一段区间中的数字之和。其查询和修改的时间复杂度均为O(logN),并且是一个在线的数据结构,可以随时修改并查询。我接下来用一道题目来介绍树状数组的几个基本操作。

二、应用:

  • 区间求和类问题(前缀和)
  • 求序列中第 K 大数
  • “图腾”类问题的统计
  • 最大值/最小值

三、模板代码:

1、区间求和类型:

#include<bits/stdc++.h>
#include<cmath>

#define mem(a,b) memset(a,b,sizeof a);
#define INF 0x3f3f3f3f

using namespace std;

typedef long long ll;

const int maxn=200010;

int n,m;
int a[maxn], rs[maxn];

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

void update_sum(int x,int val)
{
    while(x<=n)
    {
        rs[x]+=val;
        x+=lowbit(x);
    }
}

int query_sum(int x)
{
    int res=0;
    while(x>0)
    {
        res+=rs[x];
        x-=lowbit(x);
    }

    return res;
}

int main()
{
    while(~scanf("%d%d",&n,&m))
    {
        mem(rs,0);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
            update_sum(i,a[i]);
        }

        char ch[5];
        int l,r;
        while(m--)
        {
            scanf("%s%d%d",ch,&l,&r);
            if(ch[0]=='Q') printf("%d\n",query_sum(r)-query_sum(l));
            else update_sum(l,r);
        }
    }

    return 0;
}

2、最值类型:点击打开链接

四、解析(附图):

1、主要理解了“x+=lowbit(x)” 和 “x-=lowbit(x)” 和 “x--”(有些代码中是 "r--") 这三个理解了是在做什么即可,直接看图。

“x+=lowbit(x)”:访问直系父结点,比如:C[1]点开始,则会访问:C[1] --> C[2] --> C[4] --> C[8]。

“x-=lowbit(x)”:访问同一辈的左兄弟结点,比如:C[7]点开始,则会访问:C[7] --> C[6] --> C[4] --> End。

“x--”:访问左子结点,比如:C[6]点开始,则会访问:C[6] --> C[5]。

Ps:如果有时题目需要,还需要继续访问的话,需要 C[x-1] 操作,比如:访问到 C[4] 结束时,想继续访问,则需要下个从 C[3] 开始,依此类推。

2、至于利用二进制为什么这么巧妙可以得出第1点这个规律,其实我也不知道,数学就是这么神奇~

猜你喜欢

转载自blog.csdn.net/Dream_Weave/article/details/81411534
今日推荐