关于树状数组

身为蒟蒻的我 终于学会了 树状数组 但因为自己还是太蒟蒻 还是糊里糊涂的
所以写个博客理理思路

树状数组的数学模型:
在这里插入图片描述

树状数组的划分依据的原理是任何正整数都可以表示为2的幂相加的形式
如13=2^3 +2^2 +2^1 进而可以利用这一特性来进行区间求和 设想一下现在一个序列 长度为n 现在要进行区间求和 若用普通的模拟大法或者是前缀和来进行求解 那么它的时间复杂度为O(n) 但是利用树状数组这一特性区间求和 我们可以将复杂度降到O(logn)
下面呈上代码注释
但我还是要把lowbit单独拿出来讲 具体的2进制公式这里懒得写了(不会写)
总之可以抽象理解
i+=lowbit(i)就是不断为i找父亲的过程,也就是找包括i这个节点的分支的过程
假设现在为sum[1]赋值A 那么就要不断进行lowbit的操作
二进制表示1为01
进行完lowbit操作
01
+1=010(1与二进制数的第一位1相加)
也就是找到了包含1的节点2
此时就也要sum[2]+=A
然后不断以此类推
sum[4]+=A

现在将区间长度1~8的树状数组建好
此时可以对照上面的查看
1=(001) sum[1]=A[1];
2=(010) sum[2]=A[1]+A[2];
3=(011) sum[3]=A[3];
4=(100) sum[4]=A[1]+A[2]+A[3]+A[4];
5=(101) sum[5]=A[5];
6=(110) sum[6]=A[5]+A[6];
7=(111) sum[7]=A[7];
8=(1000) sum[8]=A[1]+A[2]+A[3]+A[4]+A[5]+A[6]+A[7]+A[8];
那么在进行区间x~y求和的时候
只需要找出y的前缀和减去x-1的前缀和即可求出
举个栗子
求区间2~5的和
此时找到5
然后把sumy+=sum[5]
x-=lowbit(x)向前查询
101-1=100
对应的是4
sumy+=sum[4]
此时的sumy就已经等于1~5的前缀和了
同理求出sum(x-1)
sumy-sum(x-1)即为答案

#include<cstdio>
#include<cmath>
using namespace std;
int lowbit(int x)//神奇的lowbit 
{return x&-x;}
int n,mu[1000000];
int h;
   void add(int x,int y)
  {
  while(x<=n)
  {
  mu[x]+=y;
   x=x+lowbit(x);
  }

  }
int sum(int a)
{
h=0;
while(a>0)
{
h=h+mu[a];
a=a-lowbit(a);
}
return h;
}
int main(){
cin>>n;//序列长度为n
int a;
int m,x,y;
mu[0]=0;
for(int i=1;i<=n;i++)
{
cin>>a;//输入元素a
add(i,a);//建立树状数组
}
cin>>m;//输入查询次数
string s;
for(int i=1;i<=m;i++)
{
cin>>s>>x>>y;
if(s=="SUM")//若为区间查找操作 则找出x-1的前缀与y的前缀和进行相减
{
int fx=sum(x-1);
int fy=sum(y);
cout<<fy-fx;
}
else//否则为添加操作
	add(x,y);
}      
        
         
          
           
           
    

       
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值