单点修改区间查询:
HDU1166
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int Tmax=50005;
int n,c[Tmax];
char s[10];
int lowbit(int x)
{
return x&-x;
}
int sum(int x)
{
int ret=0;
while(x>0)
{
ret+=c[x];
x-=lowbit(x);
}
return ret;
}
void add(int x,int d)
{
while(x<=n)
{
c[x]+=d;
x+=lowbit(x);
}
}
int main()
{
int T,kase,i,tmp,a,b;
scanf("%d",&T);
for(kase=1;kase<=T;kase++)
{
memset(c,0,sizeof(c));
printf("Case %d:\n",kase);
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%d",&tmp);
add(i,tmp);
}
while(scanf("%s",s)==1&&s[0]!='E')
{
scanf("%d%d",&a,&b);
if(s[0]=='Q')
printf("%d\n",sum(b)-sum(a-1));
else if(s[0]=='A')
add(a,b);
else add(a,-b);
}
}
return 0;
}
区间修改单点查询:
对a[]建一个差分数组p[i]=a[i]-a[i-1]
那么a[i]=p[1]+p[2]+…+p[i]
这串求和就可以用树状数组实现了,用C[]建树状数组,实现对p的求和
区间修改时,对x~y内每数+d,可以用add(x,d)和add(y+1,-d)实现
洛谷3368
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
const int Tmax=500005;
int n,m,C[Tmax],a[Tmax];
int lowbit(int x)
{
return x&-x;
}
void add(int x,int d)
{
while(x<=n)
{
C[x]+=d;
x+=lowbit(x);
}
}
int sum(int x)
{
int cnt=0;
while(x>0)
{
cnt+=C[x];
x-=lowbit(x);
}
return cnt;
}
int main()
{
int i,q,x,y,k;
scanf("%d%d",&n,&m);
for(i=1;i<=n;i++)
scanf("%d",&a[i]);
for(i=1;i<=n;i++)
add(i,a[i]-a[i-1]);
for(i=1;i<=m;i++)
{
scanf("%d",&q);
if(q==1)
{
scanf("%d%d%d",&x,&y,&k);
add(x,k);
add(y+1,-k);
}
else
{
scanf("%d",&x);
printf("%d\n",sum(x));
}
}
return 0;
}
区间修改区间查询:
p[]仍为a[]的差分数组,那么
a[1]+a[2]+…+a[n]
=p[1]+(p[1]+p[2])+(p[1]+p[2]+p[3])+…+(p[1]+p[2]+…+p[n])
=n*p[1]+(n-1)*p[2]+(n-3)*p[3]+…+p[n]
=n*(p[1]+p[2]+…+p[n])-(0*p[1]+2*p[2]+(n-1)*p[n])
建树状数组c1[]、c2[],分别实现对p[i]和(i-1)*p[i]求和
在修改c1时同时修改c2,求和时也做相应修改
CodeVs 1082
#include <cstdio>
#include <algorithm>
#include <cstring>
using namespace std;
typedef unsigned long long ull;
const int Tmax=200005;
int n,m;
ull c1[Tmax],c2[Tmax];
int lowbit(int x)
{
return x&-x;
}
void add(int x,ull d)
{
int i=x;
while(i<=n)
{
c1[i]+=d;
c2[i]+=(x-1)*d;
i+=lowbit(i);
}
return;
}
ull sum(int x)
{
int i=x;
ull cnt=0;
while(i>0)
{
cnt+=x*c1[i]-c2[i];
i-=lowbit(i);
}
return cnt;
}
int main()
{
int i,q,x,y;
ull d,f=0;
scanf("%d",&n);
for(i=1;i<=n;i++)
{
scanf("%llu",&d);
add(i,d-f);
f=d;
}
scanf("%d",&m);
for(i=1;i<=m;i++)
{
scanf("%d",&q);
if(q==2)
{
scanf("%d%d",&x,&y);
printf("%llu\n",sum(y)-sum(x-1));
}
else
{
scanf("%d%d%llu",&x,&y,&d);
add(x,d);
add(y+1,-d);
}
}
return 0;
}