【二维树状数组】计数问题 @JSOI2009/upcexam5911

时间限制: 1 Sec 内存限制: 128 MB
题目描述
一个n*m的方格,初始时每个格子有一个整数权值。接下来每次有2种操作:
改变一个格子的权值;
求一个子矩阵中某种特定权值出现的个数。
输入
第一行有两个数n,m。
接下来n行,每行m个数,第i+1行第j个数表示格子(i,j)的初始权值。
接下来输入一个整数q。
接下来q行,每行描述一个操作。
操作1:“1 x y c”(不含双引号)。表示将格子(x,y)的权值改成c(1<=x<=n,1<=y<=m,1<=c<=100)。
操作2:“2 x1 x2 y1 y2 c”(不含双引号,x1<=x2,y1<=y2)。表示询问所有满足格子权值为c,且x1<=x<=x2,y1<=y<=y2的格子(x,y)的个数。
输出
对于每个操作2,按照在输入中出现的顺序,依次输出一行一个整数表示所求得的个数。

注意到 1<=c<=100
对每个c值建一个二维树状数组
修改时要更新两个树状数组,一个原来权值的,一个修改后的权值的
查询类似二维前缀和

#define FILE() freopen("../../in.txt","r",stdin)
#include <bits/stdc++.h>

using namespace std;

const int maxn = 305;
int C[105][maxn][maxn],mapp[maxn][maxn];//mapp记录每一位置当前权值
int n,m;

int lowbit(int t) {
    return t&(-t);
}

void Modify(int val,int i,int j,int delta) {
    for(int x=i; x<=n; x+=lowbit(x)) {
        for(int y=j; y<=m; y+=lowbit(y)) {
            C[val][x][y]+=delta;
        }
    }
}

int Sum(int val,int i,int j) {
    int res = 0;
    for(int x=i; x>0; x-=lowbit(x)) {
        for(int y=j; y>0; y-=lowbit(y)) {
            res += C[val][x][y];
        }
    }
    return res;
}

int main() {
//    FILE();
    cin>>n>>m;
    for(int i=1; i<=n; i++) {
        for(int j=1; j<=m; j++) {
            int val;
            scanf("%d",&val);
            mapp[i][j]=val;
            Modify(val,i,j,1);
        }
    }
    int q;
    cin>>q;
    for(int i=0; i<q; i++) {
        int op,x,y,xx,yy,c;
        scanf("%d",&op);
        if(op==1) {
            scanf("%d%d%d",&x,&y,&c);
            Modify(mapp[x][y],x,y,-1);
            Modify(c,x,y,1);
            mapp[x][y] = c;
        } else {
            scanf("%d%d%d%d%d",&x,&xx,&y,&yy,&c);
            printf("%d
",Sum(c,xx,yy)-Sum(c,x-1,yy)-Sum(c,xx,y-1)+Sum(c,x-1,y-1));
        }
    }
    return 0;
}
原文地址:https://www.cnblogs.com/NeilThang/p/9356627.html