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

传送门


题目大意

给出一个 n ∗ m n*m nm的麦田(左下角为 ( 1 , 1 ) , (1,1), (1,1)右上角 ( n , m ) (n,m) (n,m)),其中有 p p p个矩形区域安装了监控,接下来有 q q q个贼想偷某个矩形范围内的庄稼,问监控能否拍到贼。

解题思路

这时一道考验二维差分+二维前缀和的一道非常好的题目。

首先我们需要将有监控的区域都置为 1 1 1,也就是每个监控区域的所有元素都加一,这时不难想到二维差分,有的元素可能被多个监控重复覆盖,那么差分矩阵还原时需要将大于 1 1 1的元素置为 1 1 1。然后对还原的矩阵求前缀和,只需要看贼偷东西的矩阵的元素和是否为矩阵面积。

题目有两大坑点:

  • 题目给的坐标是左下角为 ( 1 , 1 ) , (1,1), (1,1)右上角 ( n , m ) (n,m) (n,m)的矩阵,但是计算机存储的矩阵是左上角为 ( 1 , 1 ) , (1,1), (1,1)右下角 ( n , m ) (n,m) (n,m)。要么坐标转化一下,要么将矩阵颠倒一下。

  • 矩阵的范围是 n ∗ m ≤ 1 e 7 n*m \leq 1e7 nm1e7,无法通过数组存,要么使用 v e c t o r vector vector v e c t o r vector vector,要么就使用一维数组模拟二维数组,将下标转化一下。

一开始写了好久的一维数组一直挂,不知道哪里错了改了二维动态数组就过了,离谱
https://paste.ubuntu.com/p/6dFS6Gccst/

//
// Created by Happig on 2020/10/29
//
#include <bits/stdc++.h>
#include <unordered_map>
#include <unordered_set>

using namespace std;
#define fi first
#define se second
#define pb push_back
#define ins insert
#define Vector Point
#define ENDL "\n"
#define lowbit(x) (x&(-x))
#define mkp(x, y) make_pair(x,y)
#define mem(a, x) memset(a,x,sizeof a);
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<double, double> pdd;
const double eps = 1e-8;
const double pi = acos(-1.0);
const int inf = 0x3f3f3f3f;
const double dinf = 1e300;
const ll INF = 1e18;
const int Mod = 1e9 + 7;
const int maxn = 1e7 + 10;

void add(vector<vector<int>> &d, int i, int j, int x, int y, int val) {
    d[i][j] += val, d[x + 1][y + 1] += val;
    d[i][y + 1] -= val, d[x + 1][j] -= val;
}

int getSum(vector<vector<int>> &d, int i, int j, int x, int y) {
    return d[x][y] - d[i - 1][y] - d[x][j - 1] + d[i - 1][j - 1];
}

int main() {
    //freopen("in.txt","r",stdin);
    //freopen("out.txt","w",stdout);
    ios_base::sync_with_stdio(0), cin.tie(0), cout.tie(0);
    int n, m, p, q;
    int lx, ly, rx, ry;
    while (cin >> n >> m) {
        vector<vector<int> > d(n + 2, vector<int>(m + 2));
        cin >> p;
        while (p--) {
            cin >> lx >> ly >> rx >> ry;
            lx = n + 1 - lx, rx = n + 1 - rx;
            swap(lx, rx);
            add(d, lx, ly, rx, ry, 1);
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                d[i][j] = d[i][j] + d[i - 1][j] + d[i][j - 1] - d[i - 1][j - 1];
            }
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                if (d[i][j]) d[i][j] = 1;
            }
        }
        for (int i = 1; i <= n; i++) {
            for (int j = 1; j <= m; j++) {
                d[i][j] = d[i][j] + d[i - 1][j] + d[i][j - 1] - d[i - 1][j - 1];
            }
        }
        cin >> q;
        while (q--) {
            cin >> lx >> ly >> rx >> ry;
            lx = n + 1 - lx, rx = n + 1 - rx;
            swap(lx, rx);
            int ans = getSum(d, lx, ly, rx, ry);
            if (ans == (rx - lx + 1) * (ry - ly + 1)) cout << "YES" << endl;
            else cout << "NO" << endl;
        }
    }
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
资源包主要包含以下内容: ASP项目源码:每个资源包中都包含完整的ASP项目源码,这些源码采用了经典的ASP技术开发,结构清晰、注释详细,帮助用户轻松理解整个项目的逻辑和实现方式。通过这些源码,用户可以学习到ASP的基本语法、服务器端脚本编写方法、数据库操作、用户权限管理等关键技术。 数据库设计文件:为了方便用户更好地理解系统的后台逻辑,每个项目中都附带了完整的数据库设计文件。这些文件通常包括数据库结构图、数据表设计文档,以及示例数据SQL脚本。用户可以通过这些文件快速搭建项目所需的数据库环境,并了解各个数据表之间的关系和作用。 详细的开发文档:每个资源包都附有详细的开发文档,文档内容包括项目背景介绍、功能模块说明、系统流程图、用户界面设计以及关键代码解析等。这些文档为用户提供了深入的学习材料,使得即便是从零开始的开发者也能逐步掌握项目开发的全过程。 项目演示与使用指南:为帮助用户更好地理解和使用这些ASP项目,每个资源包中都包含项目的演示文件和使用指南。演示文件通常以视频或图文形式展示项目的主要功能和操作流程,使用指南则详细说明了如何配置开发环境、部署项目以及常见问题的解决方法。 毕业设计参考:对于正在准备毕业设计的学生来说,这些资源包是绝佳的参考材料。每个项目不仅功能完善、结构清晰,还符合常见的毕业设计要求和标准。通过这些项目,学生可以学习到如何从零开始构建一个完整的Web系统,并积累丰富的项目经验。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值