//树状数组模板
//该算法思路就是不停地二分,然后就可以优化到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;
}