洛谷P4054 [JSOI2009]计数问题

@Pelom  October 12, 2021

题意

一个$n \times m$的方格,初始时每个格子有一个整数权值
接下来每次有$2$种操作

  • 改变一个格子的权值
  • 求一个子矩阵中某种特定权值出现的个数

数据范围:$n,m \le 300,1 \le c \le 100$

题解

$n,m,c$较小,对于每个$c$开一个二维树状数组维护

代码:

#include<iostream>
#include<cstdio>
using namespace std;
const int N=300+10;
const int C=100+10;
int n,m,q,op,x1,x2,y1,y2,c;
int a[N][N];
int T[C][N][N];
inline int lowbit(int x){
    return x&-x;
}
inline void update(int u,int x,int y,int k){
    for(;x<=n;x+=lowbit(x))
        for(int i=y;i<=m;i+=lowbit(i))
            T[u][x][i]+=k;
}
inline int query(int u,int x,int y){
    int res=0;
    for(;x;x-=lowbit(x))
        for(int i=y;i;i-=lowbit(i))
            res+=T[u][x][i];
    return res;
}
int main(){
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++){
            scanf("%d",&a[i][j]);
            update(a[i][j],i,j,1);
        }
    scanf("%d",&q);
    for(;q--;){
        scanf("%d",&op);
        if(op==1){
            scanf("%d%d%d",&x1,&y1,&c);
            update(a[x1][y1],x1,y1,-1);
            a[x1][y1]=c;
            update(a[x1][y1],x1,y1,1);
        }
        else{
            scanf("%d%d%d%d%d",&x1,&x2,&y1,&y2,&c);
            printf("%d\n",query(c,x2,y2)-query(c,x1-1,y2)-query(c,x2,y1-1)+query(c,x1-1,y1-1));
        }
    }
    return 0;
}

添加新评论