树状数组 模板
树状数组的知识点:我的另一个博客
1.单点更新,求区间
#include<bits/stdc++.h> using namespace std; int n,m; const int N=1e5+10; int a[N]; int lowbit(int x) { return x&(-x); } int sum(int x) { int ans=0; for(int i=x;i>0;i-=lowbit(i)){ ans+=a[i]; } return ans; } void updata(int x,int y) { for(int i=x;i<=n;i+=lowbit(i)){ a[i]+=y; } } int main() { while(scanf("%d %d",&n,&m)==2){ memset(a,0,sizeof(a)); for(int i=1;i<=n;i++){ int x; scanf("%d",&x); updata(i,x); } while(m--){ int k,x,y; scanf("%d %d %d",&k,&x,&y); if(k==1){ updata(x,y); } else{ printf("%d\n",sum(y)-sum(x-1)); } } } return 0; }
2.区间修改 求某点
//模板 #include<bits/stdc++.h> using namespace std; int lowbit(int x) { return x&(-x); } int n; const int N=1e5+10; int s[N]; void updata(int x,int y) { for(int i=x;i<=n;i+=lowbit(i)){ s[i]+=y; } } int sum(int x) { int ans=0; for(int i=x;i>0;i-=lowbit(i)){ ans+=s[i]; } return ans; } int main() { while(scanf("%d",&n)==1,n){ memset(s,0,sizeof(s)); for(int i=0;i<n;i++){ int a,b; scanf("%d %d",&a,&b); updata(a,1); updata(b+1,-1); } for(int i=1;i<=n;i++){ if(i!=1) printf(" "); printf("%d",sum(i)); } printf("\n"); } return 0; }
模板
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> using namespace std; #define ms(i,j) memset(i,j,sizeof i); int n,m; const int maxn = 500005; int a[maxn];//a记录的是比i-lowbit(i)多的值 int lowbit(int x) { return x&(-x); } int add(int x, int v) { for (int i=x;i<=n;i+=lowbit(i)) { a[i] += v; } } int sub(int x) { int ret = 0; for (int i=x;i>0;i-=lowbit(i)) { ret += a[i]; } return ret; } int main() { scanf("%d%d", &n ,&m); ms(a,0); for (int i=1;i<=n;i++) { int x; scanf("%d", &x); add(i,x); add(i+1,-x); } for (int i=1;i<=m;i++) { int ty; scanf("%d", &ty); if(ty==1) { int x,y,k; scanf("%d%d%d", &x,&y,&k); add(x,k); add(y+1,-k); } else { int x; scanf("%d", &x); printf("%d\n", sub(x)); } } system("pause"); return 0; }
3,区间修改 区间查询
#include<iostream> #include<cstdio> #include<cmath> #include<algorithm> #include<cstring> using namespace std; int n,m; const int N=1e5+10; long long s1[N],s2[N]; int lowbit(int x) { return x&(-x); } void updata(int p,long long x) { for(int i=p;i<=n;i+=lowbit(i)){ s1[i]+=x; s2[i]+=x*p; } } long long sum(int p) { long long ans=0; for(int i=p;i>0;i-=lowbit(i)){ ans+=s1[i]*(p+1)-s2[i]; } return ans; } int main() { while(scanf("%d %d",&n,&m)==2){ memset(s1,0,sizeof(s1)); memset(s2,0,sizeof(s2)); for(int i=1;i<=n;i++){ long long x; scanf("%lld",&x); updata(i,x); updata(i+1,-x); } while(m--){ char s[10]; scanf("%s",s); if(s[0]=='C'){ int a,b; long long c; scanf("%d %d %lld",&a,&b,&c); updata(a,c); updata(b+1,-c); } else{ int a,b; scanf("%d %d",&a,&b); printf("%lld\n",sum(b)-sum(a-1)); } } } return 0; }
4.二维线段树
单点更新 区间查询
#include<bits/stdc++.h> using namespace std; int n,m; const int N=5000; long long s[N][N]; int lowbit(int x) { return x&(-x); } void updata(int x,int y,int z) { for(int i=x;i<=n;i+=lowbit(i)){ for(int j=y;j<=m;j+=lowbit(j)){ s[i][j]+=z; } } } long long sum(int x,int y) { long long res=0; for(int i=x;i>0;i-=lowbit(i)){ for(int j=y;j>0;j-=lowbit(j)){ res+=s[i][j]; } } return res; } int main() { memset(s,0,sizeof(s)); scanf("%d %d",&n,&m); int k; while(scanf("%d",&k)==1){ if(k==1){ int x,y,z; scanf("%d %d %d",&x,&y,&z); updata(x,y,z); } else{ int x1,y1,x2,y2; scanf("%d %d %d %d",&x1,&y1,&x2,&y2); printf("%lld\n",sum(x2,y2)+sum(x1-1,y1-1)-sum(x1-1,y2)-sum(x2,y1-1)); } } return 0; }
区间修改 单点查询
#include<iostream> #include<cstdio> #include<cstring> #include<string> using namespace std; const int N=1e3+10; int s[N][N]; int n; int lowbit(int x) { return x&(-x); } void updata(int x,int y,int z) { for(int i=x;i<=n;i+=lowbit(i)){ for(int j=y;j<=n;j+=lowbit(j)){ s[i][j]+=z; } } } int sum(int x,int y) { int res=0; for(int i=x;i>0;i-=lowbit(i)){ for(int j=y;j>0;j-=lowbit(j)){ res+=s[i][j]; } } return res; } int main() { int T; scanf("%d",&T); while(T--){ memset(s,0,sizeof(s)); int m; scanf("%d %d",&n,&m); while(m--){ char t[3]; scanf("%s",t); if(t[0]=='C'){ int x1,y1,x2,y2; scanf("%d %d %d %d",&x1,&y1,&x2,&y2); updata(x1,y1,1); updata(x2+1,y2+1,1); updata(x2+1,y1,-1); updata(x1,y2+1,-1); } else{ int x,y; scanf("%d %d",&x,&y); printf("%d\n",sum(x,y)%2); } } if(T) printf("\n"); } return 0; }
区间更新 区间查询
#include<bits/stdc++.h> using namespace std; const int N=2100; long long s1[N][N],s2[N][N],s3[N][N],s4[N][N]; int n,m; int lowbit(int x) { return x&(-x); } void updata(int x,int y,long long z) { for(int i=x;i<=n;i+=lowbit(i)){ for(int j=y;j<=n;j+=lowbit(j)){ s1[i][j]+=z; s2[i][j]+=x*z; s3[i][j]+=y*z; s4[i][j]+=x*y*z; } } } long long sum(int x,int y) { long long res=0; for(int i=x;i>0;i-=lowbit(i)){ for(int j=y;j>0;j-=lowbit(j)){ res+=(x+1)*(y+1)*s1[i][j]-(y+1)*s2[i][j]-(x+1)*s3[i][j]+s4[i][j]; } } return res; } int main() { while(scanf("%d %d",&n,&m)==2){ memset(s1,0,sizeof(s1)); memset(s2,0,sizeof(s2)); memset(s3,0,sizeof(s3)); memset(s4,0,sizeof(s4)); int k; while(scanf("%d",&k)==1){ if(k==1){ int a,b,c,d; long long x; scanf("%d %d %d %d %lld",&a,&b,&c,&d,&x); updata(a,b,x); updata(c+1,b,-x); updata(a,d+1,-x); updata(c+1,d+1,x); } else{ int x1,y1,x2,y2; scanf("%d %d %d %d",&x1,&y1,&x2,&y2); printf("%lld\n",sum(x2,y2)-sum(x1-1,y2)-sum(x2,y1-1)+sum(x1-1,y1-1)); } } } return 0; }