1.差分
设有一个数组a[];
它的差分数组为c[]
c[i]=a[i]-a[i-1];
当区间修改时,下标x到y的值加上k,只需维护差分数组即可
c[x]=a[x]-a[x-1],所以c[x]+=k;
c[y+1]=a[y+1]-a[y],所以c[y+1]-=k;
设b数组为c数组的前缀和数组
则b[i]=c[1]+c[2]+c[3]+c[4].....+c[i]=a[1]-a[0]+a[2]-a[1]+.....+a[i]-a[i-1]=a[i]-a[0]=a[i];
2.树状数组
lowbit函数
int lowbit(int k) { return k&-k; }
第一种
单点修改,区间查询
#include<bits/stdc++.h> using namespace std; int n,m,c[500005]; int arr[500005]; inline int lowbit(int k) { return k&-k; } void add(int x,int k) { for(int i=x; i<=n; i+=lowbit(i))c[i]+=k; } int ask(int x,int y) { int sum=0,ans=0; for(int i=x; i>0; i-=lowbit(i))sum+=c[i]; for(int i=y; i>0; i-=lowbit(i))ans+=c[i]; return ans-sum; } void slove() { scanf("%d%d",&n,&m); for(int i=1; i<=n; ++i)scanf("%d",&arr[i]),add(i,arr[i]); for(int i=1; i<=m; ++i) { int t,x,y; scanf("%d%d%d",&t,&x,&y); if(t==1)add(x,y); else printf("%d\n",ask(x-1,y)); } } int main() { slove(); return 0; }
第二种
区间修改,单点查询
差分思想,树状数组维护差分数组,进行区间修改,单点查询
#include<bits/stdc++.h> using namespace std; int n,m,arr[500005],c[500005]; inline int lowbit(int k){return k&-k;} void add(int x,int k) { for(int i=x;i<=n;i+=lowbit(i))c[i]+=k; } int ask(int x) { int ans=0; for(int i=x;i>0;i-=lowbit(i))ans+=c[i]; return ans; } void slove() { int now=0; scanf("%d%d",&n,&m); for(int i=1; i<=n; ++i) { scanf("%d",&arr[i]); add(i,arr[i]-now); now=arr[i]; } for(int i=1; i<=m; ++i) { int t,x,y,k; scanf("%d",&t); if(t==1){scanf("%d%d%d",&x,&y,&k);add(x,k),add(y+1,-k);} else{scanf("%d",&x);printf("%d\n",ask(x));} } } int main() { slove(); return 0; }