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 }

 

posted @ 2018-04-11 20:44  CHerish_OI  阅读(194)  评论(0编辑  收藏  举报