[bzoj1452][树状数组]Count

来源:互联网 发布:微信提现赚钱软件大全 编辑:程序博客网 时间:2024/05/22 16:41

Description
这里写图片描述

Input
这里写图片描述

Output
这里写图片描述

Sample Input

3 3
1 2 3
3 2 1
2 1 3
3
2 1 2 1 2 1
1 2 3 2
2 2 3 2 3 2

Sample Output

1
2

题解

二维树状数组
s[p][i][j]表示,以(1,1)为左上端点到(i,j)为右下端点的矩阵,共有多少个颜色p
然后按照一维数组转移就好了
有个小错误要提示一下,不能把矩阵展开来做,就是不能s[p][i]
因为这样的话要多一个for去枚举每一行,直接TLE。。因为这个挂了一会

#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<cmath>using namespace std;int s[110][310][310];int map[310][310];int n,m;int lowbit(int x){return x&-x;}void change(int p,int x,int y,int k){    for(int i=x;i<=n;i+=lowbit(i))        for(int j=y;j<=n;j+=lowbit(j))            s[p][i][j]+=k;}int findsum(int p,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+=s[p][i][j];    return ans; }int q;int main(){    memset(s,0,sizeof(s));    scanf("%d%d",&n,&m);    for(int i=1;i<=n;i++)    {        for(int j=1;j<=m;j++)        {            scanf("%d",&map[i][j]);            change(map[i][j],i,j,1);        }    }    scanf("%d",&q);    while(q--)    {        int op;        scanf("%d",&op);        if(op==1)        {            int x,y,c;            scanf("%d%d%d",&x,&y,&c);            change(map[x][y],x,y,-1);            map[x][y]=c;            change(map[x][y],x,y,1);        }        else        {            int x1,x2,y1,y2,c;            scanf("%d%d%d%d%d",&x1,&x2,&y1,&y2,&c);            int ans=0;            ans+=findsum(c,x2,y2);            ans-=findsum(c,x1-1,y2);ans-=findsum(c,x2,y1-1);            ans+=findsum(c,x1-1,y1-1);            printf("%d\n",ans);        }    }    return 0;}
原创粉丝点击