树状数组维护前缀和

Posted bw-orzzzzz

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了树状数组维护前缀和相关的知识,希望对你有一定的参考价值。

树状数组是用来维护序列前缀和的数据结构。它的修改与求和都是O(logn)的,效率非常高。

我们设序列为A,则树状数组c中,c[i]记录序列A的区间[ i-lowbit(i)+1 , i ]中所有数的和。 (树状数组是个好东西ovo) 技术图片

树状数组在进行区间操作时,要从上到下访问,进行单点操作时,要从下到上访问。 

树状数组维护序列前缀和的模版如下:

 

#include <iostream>
#include <cstdio>
#define maxn 500005
using namespace std;

int n,m;
int c[maxn];//c[i]存序列a中i-lowbit(i)+1到i的所有数的和(树状数组)

int read()
{
    int f=1,x=0;
    char ch;
    while(ch<0||ch>9)
    {
        if(ch==-)f=-1;
        ch=getchar();
    }
    while(ch>=0&&ch<=9)
    {
        x=x*10+ch-0;
        ch=getchar();
    }
    return f*x;
}

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

void update(int x,int y)
{
    while(x<=n)
    {
        c[x]+=y;
        x+=lowbit(x);
    }
}//将序列a[x]加上y

int sum(int x)
{
    int res=0;
    while(x>0)
    {
        res+=c[x];
        x-=lowbit(x);
    }
    return res;
}//求序列1-x的和

int main()
{
    n=read();m=read();
    for(int i=1;i<=n;i++)
    {
        //a[i]=read();
        int v=read();
        update(i,v);
    }
    for(int i=1;i<=m;i++)
    {
        int op,x,y;
        op=read();x=read();y=read();
        if(op==1)
        {
            update(x,y);
        }
        if(op==2)
        {
            int ans=sum(y)-sum(x-1);
            printf("%d\n",ans);
        }
    }

    return 0;
}

 

以上是关于树状数组维护前缀和的主要内容,如果未能解决你的问题,请参考以下文章

树状数组的应用及拓展

数据结构:树状数组 学习笔记

树状数组整理

1042.D Petya and Array 前缀 + 树状数组

P2617 Dynamic Rankings (动态开点权值线段树 + 树状数组)

Codeforces Round #629 (Div. 3) F - Make k Equal (离散化 树状数组维护前缀和)