额,大一暑假写的树状数组,翻出来存起来以后备用。
#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;
}
本文详细介绍了一种高效的数据结构——树状数组,并通过实例演示了如何使用树状数组进行前缀和的快速计算,包括初始化、求前缀和及更新操作等关键步骤。

被折叠的 条评论
为什么被折叠?



