2019中山大学程序设计竞赛-Monitor

题目地址

题目大意:给你一个n*m的矩形,在这个矩形内告诉你p个矩形(左下角和右上角坐标),问你q个问题,每次也是给你一个矩形(左下角和右上角坐标),问你每个矩形是否可以被开始给的p个矩形完全覆盖。

思路:n*m范围是1e7,无法开二维数组,二维坐标可以转化为(n-1)*m+m,用一维数组来记录每个坐标的前缀和(即为这个点与0,0点组成矩形的面积),先通过二维差分,将前缀和记录一边。因为有覆盖的情况,所以将前缀和大于0的初始化为1,在来一遍前缀和,处理好之后就可以O(1)的时间算出每个矩形是否可以覆盖。

#include<bits/stdc++.h>
using namespace std;
const int maxn=1e7+10;
int sum[maxn];
int d[maxn];
int n,m;
int fun(int x,int y)
{
    int t=m*(y-1)+x;
    if(t>=1&&t<=(n*m))
        return t;
    else
        return 0;
}
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);
    cin>>n>>m;
    int p;
    cin>>p;
    for(int i=1; i<=p; i++)
    {
        int x1,y1,x2,y2;
        cin>>y1>>x1>>y2>>x2;
        d[fun(x1,y1)]+=1;
        d[fun(x2+1,y2+1)]+=1;
        d[fun(x1,y2+1)]-=1;
        d[fun(x2+1,y1)]-=1;
    }
    for(int j=1; j<=n; j++)
        for(int i=1; i<=m; i++)
        {
            sum[fun(i,j)]=sum[fun(i,j-1)]+sum[fun(i-1,j)]-sum[fun(i-1,j-1)]+d[fun(i,j)];
        } 
    for(int i=1; i<=n*m; i++)
    {
        if(sum[i]!=0)
            sum[i]=1;
    }
//    for(int j=n; j>=1; j--)
//    {
//        for(int i=1; i<=m; i++)
//        {
//            if(sum[fun(i,j)]!=0)
//                printf("%d ",sum[fun(i,j)]);
//            else
//                printf("0 ");
//        }
//        printf("\n");
//    }
    for(int j=1; j<=n; j++)
        for(int i=1; i<=m; i++)
        {
            sum[fun(i,j)]+=sum[fun(i,j-1)]+sum[fun(i-1,j)]-sum[fun(i-1,j-1)];
        }
    int q;
    cin>>q;
    for(int i=1; i<=q; i++)
    {
        int x1,y1,x2,y2;
        cin>>y1>>x1>>y2>>x2;
        int ans=sum[fun(x2,y2)]-sum[fun(x2,y1-1)]-sum[fun(x1-1,y2)]+sum[fun(x1-1,y1-1)];
        if(ans==((x2-x1+1)*(y2-y1+1)))
            cout<<"YES"<<endl;
        else
            cout<<"NO"<<endl;
    }
}

猜你喜欢

转载自www.cnblogs.com/dongdong25800/p/10739999.html
今日推荐