【2019中山】【二维前缀和】Monitor

 【题意】:

这个题目的意思是:

有一个监视器管辖的范围用二维坐标的左下角和右上角来表示,然后有一个小偷在某个位置活动,请问能否把小偷给活动范围全部监视到。


【题解】:

1、二维差分数组维护监视器 d[][]

2、然后恢复原来的监视范围 a[][]

3、恢复后,把对应的位置置一,然后进行二维前缀和来统计 sum[][]

4、把小偷的活动范围面积求出来 与 前缀和 对比一下判断YES或NO


其实我是不知道怎么开辟二维数组的。。。

方法有两种:

用new来创建:

        d = new int* [n+10];
        a = new int* [n+10];
        sum = new int* [n+10];
        For(i,0,n+1){
            d[i] = new int [m+10];
            a[i] = new int [m+10];
            sum[i] = new int [m+10];
        }
        

用二维数组vector来开辟:

        vector< vector<int> > d(n+10);
        for(int i=0;i<n+5;i++){
            d[i].resize(m+5);
        }

        vector< vector<int> > a(n+5);
        for(int i=0;i<n+5;i++){
            a[i].resize(m+5);
        }

        vector< vector<int> > sum(n+5);
        for(int i=0;i<n+5;i++){
            sum[i].resize(m+5);
        }

 


差分数组:进行差分时候是:

 

            d[x1][y1]++;

            d[x2+1][y1]--;
            d[x1][y2+1]--;

            d[x2+1][y2+1]++;

 恢复原数组,维护二维前缀和:

        For(i,1,n){
            For(j,1,m){
                a[i][j] = a[i-1][j] + a[i][j-1] -a[i-1][j-1]+ d[i][j];

            }
        }
        For(i,1,n){
            For(j,1,m){
                if( a[i][j] >=1 )
                    a[i][j]=1;
                sum[i][j] = sum[i][j-1] + sum[i-1][j]
                            + a[i][j] - sum[i-1][j-1];
            }
        }

 

【代码】: 

#include<bits/stdc++.h>
#define For(i,L,R) for(int i=L;i<=R;i++)
using namespace std;
int n,m;
int p,q;
//int **d ,**sum,**a;
int main()
{
    int x1,x2,y1,y2,S,T;
    while(~scanf("%d%d",&n,&m)){
        /*
        d = new int* [n+10];
        a = new int* [n+10];
        sum = new int* [n+10];
        For(i,0,n+1){
            d[i] = new int [m+10];
            a[i] = new int [m+10];
            sum[i] = new int [m+10];
        }
        */
        vector< vector<int> > d(n+10);
        for(int i=0;i<n+5;i++){
            d[i].resize(m+5);
        }

        vector< vector<int> > a(n+5);
        for(int i=0;i<n+5;i++){
            a[i].resize(m+5);
        }

        vector< vector<int> > sum(n+5);
        for(int i=0;i<n+5;i++){
            sum[i].resize(m+5);
        }

        scanf("%d",&p);
        while(p--){

            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            //x1++;y1++;x2++;y2++;
            d[x1][y1]++;

            d[x2+1][y1]--;
            d[x1][y2+1]--;

            d[x2+1][y2+1]++;
            //printf("(%d %d) , (%d %d),(%d %d),(%d %d)\n",x1,y1,x2+1,y1,x1,y1+1,x2+1,y2+1);
        }

        For(i,1,n){
            For(j,1,m){
                a[i][j] = a[i-1][j] + a[i][j-1] -a[i-1][j-1]+ d[i][j];

            }
        }
        For(i,1,n){
            For(j,1,m){
                if( a[i][j] >=1 )
                    a[i][j]=1;
                sum[i][j] = sum[i][j-1] + sum[i-1][j]
                            + a[i][j] - sum[i-1][j-1];
            }
        }
        /*
        puts("A");
        For(i,0,n+1){
            For(j,0,m+1){
                printf("%d%c",a[i][j],j==m+1?'\n':' ');
            }
        }
        puts("Sum");
        For(i,0,n+1){
            For(j,0,m+1){
                printf("%d%c",sum[i][j],j==m+1?'\n':' ');
            }
        }
        */
        scanf("%d",&q);
        while(q--){
            scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
            //x1++;y1++;x2++;y2++;

            S = (y2-y1+1) *(x2-x1+1);
            T = sum[x2][y2] - sum[x2][y1-1]
            - sum[x1-1][y2] + sum[x1-1][y1-1];

            /*
            printf("%d-%d-%d+%d\n",
            sum[x2][y2],sum[x2][y1],
            sum[x1-1][y2],sum[x1-1][y1-1]);

            printf("%d %d\n",S,T);
            */

            if(S==T){
                printf("YES\n");
            }else{
                printf("NO\n");
            }
        }
    }
    return 0;
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值