树状数组模板

//树状数组模板 
//该算法思路就是不停地二分,然后就可以优化到O(qlogn)
//其实最关键的应该是二进制的应用,也就是lowbit的写法 
#include <iostream>
using namespace std;
int a[105],c[105],n;//a数组为输入的数组,c为树状数组 
int lowbit(int x)//求x二进制表示的最低位1,比如6的二进制位0110,那么lowbit返回的就是2(0010) 
{
	return x&(-x);//继续刚才那个例子,-6的二进制为所有位取反后加1,即1010,那么6&(-6)=2(0010) 
}
int query(int x)//查询1到x的和,特殊的从1开始的区间求和 
{
	int ans=0;
	while(x)//保证x大于0 
	{
		//其实就是从上到下,从大到小进行分解,然后分解求和,类似二分 
		ans+=c[x];//用ans存储和 
		x-=lowbit(x);//最重要的,也不好理解,其实就是把二进制表示的数最后一位1去掉.
		//比如6-lowbit(6)=4,即0110-0010=0100;很巧妙的方法 
	}
	return ans;
} 
void update(int x,int val)//单点修改,x为修改的下标,val为要修改的值 
{
	while(x<=n)//保证x在范围内 
	{
		//从下到上,从小到大依次修改 
		c[x]+=val;//修改 
		x+=lowbit(x); //其实就是查询的逆过程,把二进制表示的数的最后一位1加1
		//比如6+lowbits(6)=8,即0110+0010=1000 
	}
 } 
int main(int argc, char** argv) {
    
    scanf("%d",&n);
    for(int i = 1;i<=n;i++){
    	int x;
    	scanf("%d",&x);
    	update(i,x);//直接更新,同时建立c数组 
	} 
    int q;
    scanf("%d",&q);
    while(q--)
    {
    	int opt;
    	scanf("%d",&opt);
    	if(opt==1){//opt为1表示单点更新 
    		int x,val;
    		scanf("%d%d",&x,&val);
    		update(x,val);
		}
		else{//opt为2表示区间查询 
			int L,R;
			scanf("%d%d",&L,&R);
			printf("%d\n",query(R)-query(L-1));//利用前缀和的思想,求L到R的数组和,即求1到R的和减去1到L-1的和。 
		}
	}
	return 0;
}

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值