树状数组的一些操作的复习:好久没写了,复习下
单点修改,区间查询:
const int maxn=1e5;
int tr[maxn];
int n;
int lowbit(int x){return x&(-x);}
//单点修改a[x]:update(x,y)
void update(int x,int y)
{
for(int i=x;i<=n;i+=lowbit(i))
tr[i]+=y;
}
//区间查询[num1,num2]:getsum(num2)-getsum(num1-1)
int getsum(int x)
{
int ans=0;
for(int i=x;i;i-=lowbit(i))
ans+=tr[i];
return ans;
}
int a[maxn];
模板题:HDU1166
区间修改,单点查询:
就是用差分的思想,di=ai-a(i-1),这样区间修改[l,r]其实只需要改dl和d(r+1),单点查询则是Σbj,就转化成上边那种了。
模板题:洛谷3368
#include <bits/stdc++.h>
using namespace std;
const int maxn=5e5+10;
int tr[maxn];
int n;
int lowbit(int x){return x&(-x);}
//单点修改a[x]:update(x,y)
void update(int x,int y)
{
for(int i=x;i<=n;i+=lowbit(i))
tr[i]+=y;
}
//区间查询[num1,num2]:getsum(num2)-getsum(num1-1)
int getsum(int x)
{
int ans=0;
for(int i=x;i;i-=lowbit(i))
ans+=tr[i];
return ans;
}
int a[maxn];
int d[maxn];//可以不用开,方便理解点
int main()
{
int m;scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++) scanf("%d",&a[i]);
for(int i=1;i<=n;i++) d[i]=a[i]-a[i-1],update(i,d[i]);
while(m--){
int opt,x,y,k;
scanf("%d",&opt);
if(opt==1){
scanf("%d%d%d",&x,&y,&k);//[x,y]区间+k,就变成单点修改b[x],b[y+1]
update(x,k),update(y+1,-k);
}
else{
scanf("%d",&x);//单点查询x,就变成区间求和b1+b2+...+bx
printf("%d\n",getsum(x));
}
}
return 0;
}