BZOJ1452 [JSOI2009]Count

题意

一个N*M的方格,初始时每个格子有一个整数权值,接下来每次有2个操作:
改变一个格子的权值
求一个子矩阵中某个特定权值出现的个数

n,m<=300,Q<=5000,1<=c<=100

分析

话说哪个好事者把这题标签打成树套树的?

参照hzwer的题解。

对于每种颜色开一个二维树状数组水过。

时间复杂度\(O((nm+q)\log_2n\log_2m)\),空间复杂度\(O(nmc)\)

代码

#include<bits/stdc++.h>
#define rg register
#define il inline
#define co const
template<class T>il T read(){
    rg T data=0,w=1;
    rg char ch=getchar();
    while(!isdigit(ch)){
        if(ch=='-') w=-1;
        ch=getchar();
    }
    while(isdigit(ch))
        data=data*10+ch-'0',ch=getchar();
    return data*w;
}
template<class T>il T read(rg T&x){
    return x=read<T>();
}
typedef long long ll;

int n,m,q;
int mp[301][301];
int t[101][301][301];
#define lowbit(x) (x&-x)
void update(int x,int y,int c,int val){
    for(int i=x;i<=n;i+=lowbit(i))
        for(int j=y;j<=m;j+=lowbit(j))
            t[c][i][j]+=val;
}
int ask(int x,int y,int c){
    int re=0;
    for(int i=x;i;i-=lowbit(i))
        for(int j=y;j;j-=lowbit(j))
            re+=t[c][i][j];
    return re;
}

int main(){
//  freopen(".in","r",stdin);
//  freopen(".out","w",stdout);
    read(n),read(m);
    for(int i=1;i<=n;++i)
        for(int j=1;j<=m;++j)
            update(i,j,read(mp[i][j]),1);
    read(q);
    while(q--){
        int opt=read<int>();
        if(opt==1){
            int x=read<int>(),y=read<int>();
            update(x,y,mp[x][y],-1);
            update(x,y,read(mp[x][y]),1);
        }
        else{
            int x1=read<int>(),x2=read<int>(),y1=read<int>(),y2=read<int>(),c=read<int>();
            printf("%d\n",ask(x2,y2,c)+ask(x1-1,y1-1,c)-ask(x1-1,y2,c)-ask(x2,y1-1,c));
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/autoint/p/10371775.html