2018山东冬令营:UPC 计数问题 (二维树状数组)


计数问题

时间限制: 1 Sec  内存限制: 128 MB
提交: 185  解决: 51
[提交][状态][讨论版][命题人:admin]

题目描述

 一个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,按照在输入中出现的顺序,依次输出一行一个整数表示所求得的个数。

样例输入

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

样例输出

1

2

提示

对于30%的数据n,m<=30,q<=10000
对于100%的数据 n,m<=300,q<=100000,1<=c<=100



RMQ 查询问题; 

m次查询  很且数量很大,   所以想到往树状数组上靠拢,  然后 这个地方又是 统计 x,y 的  那就时二维树状数组

但题意 又要 求 某个数的个数,  所以  tree【】【】【】  开到三维,  C不到100 很ok

 更新时,  先把 对应的位置上的数 全部-1   然后再把要变成的值+1   保证 全部变成, 并且更新节点


[code]

#include <iostream>
#include <bits/stdc++.h>
#include <string.h>
#define mem(a,b) memset(a,b,sizeof(a))

using namespace std;
const int MOD=1e9+7;
const int MAXN=1e5+15;
const int INF=0x3f3f3f3f;
typedef long long ll;

inline ll qpow(ll x,ll n){ll res=1;for(;n;n>>=1){if(n&1)res=(res*x);x=(x*x);}return res;}
const int N=305;
int a[310][310];
int tree[305][305][105];
int n,m;
int lowbit(int x)
{
    return x&(-x);
}
void update(int x,int y,int c,int k )
{
    int i, j;
    for(i=x;i<=m;i+=lowbit(i))
    {
        for(j=y; j<=n; j+=lowbit(j))
        {
            tree[i][j][c] += k;
        }
    }
}

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

    scanf("%d %d",&n,&m);
    int sum=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            scanf("%d",&a[i][j]);
            update(i,j,a[i][j],1);
        }
    }
    int q;
    scanf("%d",&q);
    while(q--)
    {
        int f;
        scanf("%d",&f);
        if(f==1)
        {
            int x,y,z;
            scanf("%d %d %d",&x,&y,&z);
            update(x,y,a[x][y],-1);
            update(x,y,z,1);
            a[x][y]=z;
        }
        else
        {
            int x1,x2,y1,y2,z;
            scanf("%d %d %d %d %d",&x1,&x2,&y1,&y2,&z);
            int sum= Sum(x2,y2,z)-Sum(x2,y1-1,z)-Sum(x1-1,y2,z)+Sum(x1-1,y1-1,z);
            printf("%d\n",sum);
        }
    }
    return 0;
}

123

posted @ 2018-03-22 22:11  Sizaif  阅读(145)  评论(0编辑  收藏  举报