bzoj1452: [JSOI2009]Count(树状数组)
1503: [NOI2004]郁闷的出纳员
题目:传送门
题解:
二维树状数组裸题
将a[x][y][c]表示的是[1,1]到[x,y]这个矩阵中值为c的格子个数(二维前缀和思想)
最后利用矩阵区间求和的方法加加减减就OK
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 using namespace std; 7 int n,m; 8 int mp[310][310],a[310][310][110]; 9 int lowbit(int x){return x&-x;} 10 void change(int x,int y,int c,int d) 11 { 12 int t=y; 13 while(x<=n) 14 { 15 y=t; 16 while(y<=m) 17 { 18 a[x][y][c]+=d; 19 y+=lowbit(y); 20 } 21 x+=lowbit(x); 22 } 23 } 24 int getsum(int x,int y,int c) 25 { 26 int t=y,sum=0; 27 while(x) 28 { 29 y=t; 30 while(y) 31 { 32 sum+=a[x][y][c]; 33 y-=lowbit(y); 34 } 35 x-=lowbit(x); 36 } 37 return sum; 38 } 39 int main() 40 { 41 scanf("%d%d",&n,&m);memset(a,0,sizeof(a)); 42 for(int i=1;i<=n;i++)for(int j=1;j<=m;j++)scanf("%d",&mp[i][j]),change(i,j,mp[i][j],1); 43 int Q;scanf("%d",&Q); 44 while(Q--) 45 { 46 int opt;scanf("%d",&opt); 47 if(opt==1) 48 { 49 int x,y,c;scanf("%d%d%d",&x,&y,&c); 50 change(x,y,mp[x][y],-1);mp[x][y]=c;change(x,y,c,1); 51 } 52 else 53 { 54 int x1,x2,y1,y2,c;scanf("%d%d%d%d%d",&x1,&x2,&y1,&y2,&c); 55 printf("%d\n",getsum(x2,y2,c)-getsum(x1-1,y2,c)-getsum(x2,y1-1,c)+getsum(x1-1,y1-1,c)); 56 } 57 } 58 return 0; 59 }