牛客多校联赛第二场j-farm(二维树状数组+hash)

题目链接:传送门

题目大意:

有一个n*m的矩形,每个位置有一个数。有T次操作,每次往一个子矩形的每个格子中放入一个数。
求有多少个格子中被放入了至少一个与对应位置不相同的数。
n*m<=1e6,T<=1e6

题目思路:

每次放入一个数,如果操作若干次后,将放入的所有数相加除以对应位置的数,如果整除则放入的数和对应的位置数相同。这是一个不充分但必要条件。

即可能会出现一些特殊情况,比如放入了1,2,但相应位置的数为3则结果时符合,但是与事实不符。

所以我们用hash的方法,减少这种特殊的情况,当放入的数和相应的位置的数足够大的时候,这种概率就会被无限的缩小。

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=1e6+5;

struct BIT_2D
{
    int n,m;
    vector<ll> C[maxn];
    int lowbit(int x){return x&(-x);}
    void init(int n,int m) //初始化n行m列矩阵
    {
        this->n=n;
        this->m=m;
        for(int i=1;i<=n;i++)
        {
            C[i].clear();
            for(int j=0;j<=m;j++) C[i].push_back(0);
        }
    }
    void add(int x,int y,ll val)
    {
        for(int i=x;i<=n;i+=lowbit(i))
            for(int j=y;j<=m;j+=lowbit(j)) C[i][j]+=val;
    }
    void range_add(int x1,int y1,int x2,int y2,ll x) //左上角为(x1,y1)右下角为(x2,y2)的矩阵全部加上x
    {
        add(x1,y1,x);
        add(x1,y2+1,-x);
        add(x2+1,y1,-x);
        add(x2+1,y2+1,x);
    }
    ll ask(int x,int y) //查询点(x,y)的值
    {
        ll ret=0;
        for(int i=x;i>0;i-=lowbit(i))
            for(int j=y;j>0;j-=lowbit(j)) ret+=C[i][j];
        return ret;
    }
}BIT;

int n,m,T;
vector<ll> a[maxn];

ll has[maxn];
inline ll get_rand(int m,int n)
{
    return rand()%(n-m+1)+m;
}
void myhash(int m)
{
    srand(time(NULL));
    for(int i=1;i<=m;i++) has[i]=get_rand(1e6,9e6);
}

int main()
{
    scanf("%d%d%d",&n,&m,&T);
    myhash(n*m);
    BIT.init(n,m);
    for(int i=1;i<=n;i++)
    {
        a[i].clear(); a[i].push_back(0);
        for(int j=1,type;j<=m;j++)
        {
            scanf("%d",&type);
            a[i].push_back(has[type]);
        }
    }
    for(int i=1;i<=T;i++)
    {
        int x1,y1,x2,y2,k;
        scanf("%d%d%d%d%d",&x1,&y1,&x2,&y2,&k);
        BIT.range_add(x1,y1,x2,y2,has[k]);
    }

    int ans=0;
    for(int i=1;i<=n;i++)
    {
        for(int j=1;j<=m;j++)
        {
            if(BIT.ask(i,j)%a[i][j] != 0) ans++;
        }
    }
    cout<<ans<<endl;
}
/*
2 2 2
1 2
2 3
1 1 2 2 2
2 1 2 1 1

3
*/

猜你喜欢

转载自blog.csdn.net/qq_36782366/article/details/81391604