DestinHistoire

 

BZOJ-1452 [JSOI2009]Count(二维树状数组)

题目描述

  给一个 \(n\times m\) 的矩阵和 \(q\) 次操作,初始时每个格子有一个数字。有 \(2\) 种操作:

  操作 \(1\)1 x y c,将格子 \((x,y)\) 的数字改成 \(c\)

  操作 \(2\)2 x1 x2 y1 y2 c,询问所有满足格子数字为 \(c\),且 \(x1\leq x\leq x2,y1\leq y\leq y2\) 的格子\((x,y)\) 的个数。

  数据范围:\(n,m\leq 300,q\leq 5000.1\leq c\leq 100\)

分析

  \(c\) 的值域很小,最大只有 \(100\),用 \(100\) 个二维树状数组存储每个数在矩阵中出现的次数。

  对于操作 \(1\),把 \((x,y)\)\(a\) 修改为 \(c\),值 \(a\) 的树状数组对应位置的出现次数 \(-1\),值 \(b\) 的树状数组对应位置的出现次数 \(+1\)

  对于操作 \(2\),直接输出出现次数。

代码

#include<bits/stdc++.h>
using namespace std;
const int N=310;
int n,m;
int c[N][N][N];
int a[N][N];
int lowbit(int x)
{
    return x&-x;
}
void add(int val,int x,int y,int z)
{
    for(int i=x;i<=n;i=i+lowbit(i))
        for(int j=y;j<=m;j=j+lowbit(j))
            c[val][i][j]+=z;
}
int query(int val,int x,int y)
{
    int ans=0;
    for(int i=x;i;i=i-lowbit(i))
        for(int j=y;j;j=j-lowbit(j))
            ans=ans+c[val][i][j];
    return ans;
}
int main()
{
    cin>>n>>m;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            scanf("%d",&a[i][j]);
            add(a[i][j],i,j,1);
        }
    }
    int q;
    cin>>q;
    while(q--)
    {
        int op;
        scanf("%d",&op);
        if(op==1)
        {
            int x,y,c;
            scanf("%d %d %d",&x,&y,&c);
            add(a[x][y],x,y,-1);
            a[x][y]=c;
            add(c,x,y,1);
        }
        else
        {
            int X1,X2,Y1,Y2,c;
            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;
}

posted on 2020-12-13 12:44  DestinHistoire  阅读(76)  评论(0编辑  收藏  举报

导航