树状数组的功能:
1、完成某一个 点 的修改,然后快速得到其前任意项的和。
2、引申出来的作用是,计算A[L]~A[R]的和;
下面是树状数组的实现代码,和其中有关的操作:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define mem(a) memset(a, 0, sizeof(a));
const int maxn = 100010;
int c[maxn];
int a[maxn];
int n;
int lowbit(int x)
{
return x&(-x);
}
int sum(int x)
{
int cnt=0;
while(x>0)
{
cnt+=c[x];
x-=lowbit(x);
}
return cnt;
}
void add(int x,int d)
{
while(x<=n)
{
c[x]+=d;
x+=lowbit(x);
}
}
int main()
{
while(scanf("%d",&n)!=EOF)
{
mem(c);mem(a);
///这是用所给的n个值初始化树状数组
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
add(i,a[i]);
}
///(帮助理解)C数组中的每个元素,都是A数组中的一段连续和;
for(int i=1;i<=n;i++){
printf("c[%d] = %d\n",i,c[i]);
}
///(帮助理解)用sum(i)可以快速取得a[1]~a[i]的连续和;
for(int i=1;i<=n;i++){
printf("sum[%d] = %d\n",i,sum(i));
}
///add(id,增量d),其作用是使树状数组中A[id]的值增加d;(但是其上输入的a[id]的值并没有变)
///add(id,num-a[id])可以实现将A[id]的值变成num
///下面代码中有对sum值的二分查找,是个很好的技巧。
scanf("%d",&k);
for(int i=1;i<=k;i++)
{
getchar();
scanf("%c",&ch);
if(ch=='p')
{
int id,num;
scanf("%d%d",&id,&num);
add(id,num-a[id]);
a[id]=num;
}
else if(ch == 'q')
{
int r;
scanf("%d",&r);
int left_=0;int right_=n;
while(left_<right_)
{
int m=left_+(right_-left_)/2;
if(sum(m)>=r) right_=m;
else left_=m+1;
}
printf("%d\n",left_);
}
}
}
return 0;
}
本文详细介绍了树状数组的基本概念及其核心功能:快速完成单点更新并获取前缀和。通过具体代码示例,展示了如何使用树状数组进行区间求和及单点更新操作,并提供了实用的二分查找技巧。
536

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



