一维树状数组模板:
int lowbit(int x) { return x&(-x); } void add(int x,int val)//下标为x值增加val { while(x<=n)//n是数组的规模,容易出错 { c[x]+=val; x+=lowbit(x); } } int sum(int x)//求下标1~x的数组之和 { int ans=0; while(x>0) { ans+=c[x]; x-=lowbit(x); } return ans; }
主函数: 模板一:修改某个点,求某段区间的和 int c[200010]//树状数组,a[200010]//普通数组; memset(c,0,sizeof(c));//建立树状数组 for(int i=1;i<=n;i++)//必须从1开始存入 { scanf("%d",&a[i]); add(i,a[i]); } cout<<sum(r)-sum(l-1)<<endl;//输出[l,r]之和 add(z,b-a[z]);//修改a[z]=b a[z]=b; 模板2:修改某个区间,求某个点的值 memset(c,0,sizeof(c)); for(int t=0;t<=n-1;t++) { int a,b; scanf("%d%d",&a,&b);//区间[a,b]增加1 add(a,1); add(b+1,-1); } cout<<sum(i)<<endl;//求i的值
模板1:
修改某个点,求某段区间的和
poj 2352
Input
Output
Sample Input
5 1 1 5 1 7 1 3 3 5 5
Sample Output
1 2 1 1 0
Hint
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<algorithm> #define LL long long #define inf 0x3f3f3f3f using namespace std; int n; int c[32010]; int result[32010]; int lowbit(int x) { return x&(-x); } void add(int x,int val) { while(x<=32010)//注意数组的规模 { c[x]+=val; x+=lowbit(x); } } int sum(int x) { int ans=0; while(x>0) { ans+=c[x]; x-=lowbit(x); } return ans; } int main() { while(cin>>n) { memset(c,0,sizeof(c)); memset(result,0,sizeof(result)); for(int i=0;i<=n-1;i++) { int x,y; scanf("%d%d",&x,&y); int t=sum(++x); result[t]++; add(x,1); } for(int i=0;i<=n-1;i++) cout<<result[i]<<endl; } return 0; }
修改某个区间,求某个点的值
3 1 1 2 2 3 3 3 1 1 1 2 1 3 0
1 1 1 3 2 1
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<vector> #include<string> #include<algorithm> #define LL long long #define inf 0x3f3f3f3f using namespace std; int c[100010]; int n; int lowbit(int x) { return x&(-x); } void add(int x,int val) { while(x<=n) { c[x]+=val; x+=lowbit(x); } } int getsum(int x) { LL ans=0; while(x>0) { ans+=c[x]; x-=lowbit(x); } return ans; } int main() { while(cin>>n) { if(n==0) return 0; memset(c,0,sizeof(c)); for(int t=0;t<=n-1;t++) { int a,b; scanf("%d%d",&a,&b); add(a,1); add(b+1,-1); } for(int i=1;i<=n-1;i++) cout<<getsum(i)<<" "; cout<<getsum(n)<<endl; } return 0; }
二维树状数组模板
int lowbit(int x) { return x&(-x); } void add(int x,int y,int val)//a[x][y]增加val { for(int i=x;i<=n;i+=lowbit(i)) for(int j=y;j<=n;j+=lowbit(j)) c[i][j]+=val; } int getsum(int x,int y)//1~x,1~y之和 { int ans=0; for(int i=x;i>=1;i-=lowbit(i)) for(int j=y;j>=1;j-=lowbit(j)) ans+=c[i][j]; return ans; }
主函数: 模板1:修改某个点的值,求某个区域的和 int c[1010][1010]//树状数组,a[1010][1010]//普通数组; memset(c,0,sizeof(c));//建立树状数组 for(int i=1;i<=n;i++)表示个数 { scanf("%d%d%d",&m,&n,&x);//a[m][n]=x add(m,n,x); } 区间[xmax,ymax]和: getsum(xmax,ymax)-getsum(xmin-1,ymax)-getsum(xmax,ymin-1)+getsum(xmin-1,ymin-1);//查询[xmin,xmax],[ymin,ymax]之和 模板2:改变某个区域的值,求某个点的值 memset(c,0,sizeof(c)); 改变左上角为(x1,y1),右上角(x2,y2)区域增加x scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&x); add(x1,y1,1); add(x1,y2+1,1); add(x2+1,y1,1); add(x2+1,y2+1,1); 求点的值:cout<<getsum(x,y)<<endl;
5 B 581 145 B 581 145 Q 0 600 0 200 D 581 145 Q 0 600 0 200
1 0
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<string> #include<algorithm> #define LL long long #define inf 0x3f3f3f3f #define n 1006 using namespace std; int c[1010][1010]; int visited[1010][1010]; int lowbit(int x) { return x&(-x); } void add(int x,int y,int val) { for(int i=x;i<=n;i+=lowbit(i)) for(int j=y;j<=n;j+=lowbit(j)) c[i][j]+=val; } int getsum(int x,int y) { int ans=0; for(int i=x;i>=1;i-=lowbit(i)) for(int j=y;j>=1;j-=lowbit(j)) ans+=c[i][j]; return ans; } int main() { int m; cin>>m; memset(visited,0,sizeof(visited)); memset(c,0,sizeof(c)); while(m--) { char ch; cin>>ch; if(ch=='B') { int a,b; cin>>a>>b; a++;b++; if(!visited[a][b]) { add(a,b,1); visited[a][b]=1; } } if(ch=='D') { int a,b; cin>>a>>b; a++;b++; if(visited[a][b]) { add(a,b,-1); visited[a][b]=0; } } if(ch=='Q') { int x1,y1,x2,y2; cin>>x1>>x2>>y1>>y2; x1++;x2++;y1++;y2++; int xmax=max(x1,x2); int xmin=min(x1,x2); int ymax=max(y1,y2); int ymin=min(y1,y2); cout<<getsum(xmax,ymax)-getsum(xmin-1,ymax)-getsum(xmax,ymin-1)+getsum(xmin-1,ymin-1)<<endl; } } return 0; }
模板2:poj 2155
Description
Input
Output
Sample Input
1 2 10 C 2 1 2 2 Q 2 2 C 2 1 2 1 Q 1 1 C 1 1 2 1 C 1 2 1 2 C 1 1 2 2 Q 1 1 C 1 1 2 1 Q 2 1
Sample Output
1 0 0 1
#include<iostream> #include<cstring> #include<cstdio> #include<cmath> #include<vector> #include<string> #include<algorithm> #define LL long long #define inf 0x3f3f3f3f using namespace std; int c[1010][1010]; int n; int lowbit(int x) { return x&(-x); } void add(int x,int y,int val)//a[x][y]增加val { for(int i=x;i<=n;i+=lowbit(i)) for(int j=y;j<=n;j+=lowbit(j)) c[i][j]=(c[i][j]+val)%2; } int getsum(int x,int y)//1~x,1~y之和 { int ans=0; for(int i=x;i>=1;i-=lowbit(i)) for(int j=y;j>=1;j-=lowbit(j)) ans=(ans+c[i][j])%2; return ans; } int main() { int T; cin>>T; while(T--) { int m; cin>>n>>m; memset(c,0,sizeof(c)); while(m--) { char ch[5]; scanf("%s",ch); if(ch[0]=='C') { int x1,y1,x2,y2; scanf("%d%d%d%d",&x1,&y1,&x2,&y2); add(x1,y1,1); add(x1,y2+1,1); add(x2+1,y1,1); add(x2+1,y2+1,1); } else { int x,y; scanf("%d%d",&x,&y); cout<<getsum(x,y)<<endl; } } if(T) cout<<endl; } return 0; }