HDU - 6514 Monitor ( 二位前缀和+差分 )

HDU - 6514 Monitor ( 二位前缀和+差分 )

题意:

给你n和m,表示有一个n*m的矩阵(n>=1, m>=1, n*m<=1e7),初始全0,接下来一个数p(p<=1e6),接下来p个矩阵的左上角和右下角的坐标。

把这位于这些矩阵内的格子置为1,再接下来一个数q(1<=1e6),接下来q个矩阵的左上角和右下角的坐标,对于每个矩阵,如果它包含的每个格子都是1,则输出YES,否则输出NO。


思路:

因为n和m都可能是1e7的,所以没法开二维的数组,直接开一个1e7的一维数组当做二维数组用。在维护二维前缀和前需要用差分思想,把1e6组插入给记录下来,然后处理差分数组,变成计数数组,再进行二维前缀和。

二维差分时注意需要在哪些点加减,这里画图理解一下。

下图表示,在这个矩形范围内全部加1, 那么只需要在图示四个点标记差分数组就可以了。

代码:

#include <bits/stdc++.h>

using namespace std;

const int maxn = 3e7+10;
int a[maxn];
int n,m;

int getid( int i, int j )
{
    return i*(m+2)+j; // 在一行里可能用到0,和n+1, 所以需要乘(m+2)
}

int main()
{
    int x1,x2,y1,y2,l,q;
    while ( cin>>n>>m ) {
        cin >> l;
        memset(a,0,sizeof(a));
        while ( l-- ) {
            scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
            a[ getid(x1,y1) ] ++;
            a[ getid(x1,y2+1) ] --;
            a[ getid(x2+1,y1) ] --;
            a[ getid(x2+1,y2+1) ] ++;
        }
        for ( int i=1; i<=n; i++ ) {  //把差分数组转化成计数数组
            for ( int j=1; j<=m; j++ ) {
                a[ getid(i,j) ] += a[ getid(i-1,j) ] + a[ getid(i,j-1) ] - a[ getid(i-1,j-1) ];
            }
        }
        for ( int i=1; i<=n; i++ ) {  //大于1的当成1
            for ( int j=1; j<=m; j++ ) {
                if ( a[ getid(i,j) ]>0 ) a[ getid(i,j) ] = 1;
            }
        }
        for ( int i=1; i<=n; i++ ) {  //把计数数组转换成二维前缀和
            for ( int j=1; j<=m; j++ ) {
                a[ getid(i,j) ] += a[ getid(i-1,j) ] + a[ getid(i,j-1) ] - a[ getid(i-1,j-1) ];
            }
        }

        cin >> q;
        while ( q-- ) {
            scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
            int tot = a[ getid(x2,y2) ] - a[ getid(x2,y1-1) ] - a[ getid(x1-1,y2) ] + a[ getid(x1-1,y1-1) ];
            if ( tot==(x2-x1+1)*(y2-y1+1) ) printf("YES\n");
            else printf("NO\n");
        }
    }

    return 0;
}

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值