bzoj1452[JSOI2009]Count

bzoj1452[JSOI2009]Count

题意:

n*m矩阵,支持两个操作,修改某个格子权值和查询某个子矩阵特定权值出现次数。n,m≤300,权值为1到100的整数。

题解:

原来二维前缀和也可以用树状数组维护,只要那个不断增加/减少lowbit的循环再嵌套一层就行了。同时因为权值是1到100的整数,所以二维前缀和多一维维护特定权值个数就行了。

代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #define maxn 301
 5 #define inc(i,j,k) for(int i=j;i<=k;i++)
 6 #define lb(x) x&-x
 7 using namespace std;
 8 
 9 int sm[maxn][maxn][maxn/3+1],col[maxn][maxn],n,m;
10 void update(int x,int y,int z,int v){
11     for(int i=x;i<=n;i+=lb(i))for(int j=y;j<=m;j+=lb(j))sm[i][j][z]+=v;
12 }
13 int query(int x,int y,int z){
14     int q=0; for(int i=x;i>=1;i-=lb(i))for(int j=y;j>=1;j-=lb(j))q+=sm[i][j][z]; return q;
15 }
16 inline int read(){
17     char ch=getchar(); int f=1,x=0;
18     while(ch<'0'||ch>'9'){if(ch=='-')f=-1; ch=getchar();} while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
19     return f*x;
20 }
21 int main(){
22     n=read(); m=read(); inc(i,1,n)inc(j,1,m){col[i][j]=read(); update(i,j,col[i][j],1);} int q=read();
23     inc(i,1,q){
24         int x=read();
25         if(x==1){
26             int x0=read(),x1=read(),x2=read();
27             update(x0,x1,col[x0][x1],-1); update(x0,x1,x2,1); col[x0][x1]=x2;
28         }
29         if(x==2){
30             int x1=read(),x2=read(),y1=read(),y2=read(),c=read();
31             printf("%d\n",query(x2,y2,c)-query(x1-1,y2,c)-query(x2,y1-1,c)+query(x1-1,y1-1,c));
32         }
33     }
34     return 0;
35 }

 

20160603

posted @ 2016-07-20 19:58  YuanZiming  阅读(287)  评论(0编辑  收藏  举报