#include
using namespace std;
int n,m,i,num[100001],t[200001],l,r;//num:原数组;t:树状数组
int lowbit(int x)
{
return x&(-x);
}
void change(int x,int p)//将第x个数加p
{
while(x<=n)
{
t[x]+=p;
x+=lowbit(x);
}
return;
}
int sum(int k)//前k个数的和
{
int ans=0;
while(k>0)
{
ans+=t[k];
k-=lowbit(k);
}
return ans;
}
int ask(int l,int r)//求l-r区间和
{
return sum(r)-sum(l-1);
}
int main()
{
cin>>n>>m;
for(i=1;i<=n;i++)
{
cin>>num[i];
change(i,num[i]);
}
for(i=1;i<=m;i++)
{
cin>>l>>r;
cout<<ask(l,r)<<endl;
}
return 0;
}
a[]原数组 d[]差分数组,即d[i]=a[i]-a[i-1]
易得a[i]=d1+d2+d3+…+di
当需要将[l,r]内的元素都加上x时,由于d是差分数组,因此只需将d[l]+x,d[r+1]-x即可
使用树状数组维护d数组即可快速实现单点查询和区间修改操作
//区间修改时修改d[l]和d[r+1]的值
void change(int x,int p)
{
while(x<n){
d[x]+=p;
x+=lowbit(x);
}
}
//区间修改 ,使区间[l,r]的数加上x->只需使d[l]+x,d[r+1]-x即可
void update(int l,int r,int p)
{
change(l,x);
change(r+1,-x);
}
//单点查询,查询x位置的值
int getvalue(int x)
{
int p=0;
while(x>0){
sum+=d[x];
x-=lowbit(x);
}
return p;
}
a[]原数组 d[]差分数组,即d[i]=a[i]-a[i-1]
易得a[i]=d1+d2+d3+…+di
设sum(1,k)表示a1+a2+a3+…+ak
那么sum(1,k)=d1 + (d1+d2) + (d1+d2+d3) + … + (d1+d2+d3+…+dk)=k*(d1+d2+d3+…+dk) - (0d1 + 1d2 + 2*d3 +…+ (k-1)*dk)
因此可以用树状数组维护两个数组d1[],d2[]即可,d1[]维护di,d2[]维护(i-1)*di
int a[N],d1[N],d2[N];//a原数组 d1 d2树状数组
void change(int t[],int x,int p)
{
while(x<n){
t[x]+=p;
x+=lowbit(x);
}
}
//区间修改 区间[l,r]内的数加上p
void update(int l,int r,int p)
{
//d1数组
change(d1,l,p);
change(d1,r+1,-p);
//d2数组
change(d2,l,(l-1)*p);
change(d2,r+1,-r*p);
}
int getsum(int t[],int x)
{
int val=0;
while(x>0){
val+=t[x];
x-=lowbit(x);
}
return val;
}
//计算a1+a2+...+an的和
int sum(int x)
{
int ans1,ans2;
ans1=x*getsum(d1,x);
ans2=getsum(d1,x);
return ans1-ans2;
}
//区间和查询 ,计算区间[l,r]内的元素和
int query(int l,int r)
{
return sum(r)-sum(l-1);
}
int a[N],t[N];//a[] 原数组 t[]树状数组
//单点更新
void update(int x)
{
while(x<=n){
t[x]=a[x];
int len=lowbit(x);
for(int i=1;i<len;i<<=1)
t[x]=max(t[x],t[x-i]);
x+=lowbit(x);
}
}
//区间最值查询 查询区间[l,r]的最值
int query(int l,int r)
{
int ans=0;
while(r>=l){
ans=max(a[r],ans);
r--;
while(r-lowbit(r)>=x){
ans=max(t[r],ans);
r-=lowbit(r);
}
}
return ans;
}
单点修改+区间和查询
//单点修改
void change(int x,int y,int p)
{
for(int i=x;i<=n;i+=lowbit(i))
for(int j=y;j<=n;j+=lowbit(j))
t[i][j]+=p;
}
//区间查询
int query(int x,int y)
{
int ans=0;
for(int i=x;i>=0;i-=lowbit(i))
for(int j=y;j>=0;j-=lowbit(j))
ans+=t[i][j];
return ans;
}