【算法模板】树状数组,手写留念~

额,大一暑假写的树状数组,翻出来存起来以后备用。

 

#include "bits/stdc++.h"
using namespace std;
#define INF 999999999
#define inf 10009
//后缀数组的学习:预处理nlogn,实现logn的前缀和求
//后缀数组下标自1始!用C[i]来表示,其核心就是lowbit(i)
//C[i]体现的是i的二进制最后一个1所对应的大小
//而有趣的是,C[i]中对应的元素个数,正是lowbit(i)的大小
int a[inf];
int c[inf];
int n;
int lowbit(int i)
{
    return i&-i;    //lowbit的计算很神奇,用补码来计算
}
int init_c()//计算后缀数组,nlogn
{
    memset(c,0,sizeof c);
    int i,j;
    for(i=1;i<=n;i++)
    {
        int t=lowbit(i);
        for(j=i-t+1;j<=i;j++)
            c[i]+=a[j]; //加的是a[j],别写错a[i]了
    }
}
int cal_sum(int k)  //求前缀和Sk,包括a[k]
{
    int sum=0;
    while(k>0)
    {
        sum+=c[k];
        k-=lowbit(k);
    }
    return sum;
}
void update(int k,int y)  //修改点a[k],改为y,维护树状数组
{
    int t=y-a[k];
    a[k]=y;
    while(k<=n)
    {
        c[k]+=t;
        k+=lowbit(k);
    }
}
int main()
{
    int i,j,m;
    scanf("%d%d",&n,&m);
    for(i=1;i<=n;i++)
        scanf("%d",&a[i]);
    init_c();
    for(i=1;i<=n;i++)
    printf("%d ",c[i]);
    printf("\n");
    while(m--)
    {
        int k;
        scanf("%d",&k);
        if(k==0)
        {
            int l,r;
            scanf("%d%d",&l,&r);
            printf("%d\n",cal_sum(r)-cal_sum(l-1));
        }
        else
        {
            int x,y;
            scanf("%d%d",&x,&y); //把a[x]变成y
            update(x,y);
        }
    }

    return 0;
}

 

你可能感兴趣的:(数据结构,常用算法模板)