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

http://acm.hdu.edu.cn/showproblem.php?pid=6514

Problem Description

Xiaoteng has a large area of land for growing crops, and the land can be seen as a rectangle of n×m. 
But recently Xiaoteng found that his crops were often stolen by a group of people, so he decided to install some monitors to find all the people and then negotiate with them.
However, Xiao Teng bought bad monitors, each monitor can only monitor the crops inside a rectangle. There are p monitors installed by Xiaoteng, and the rectangle monitored by each monitor is known. 
Xiao Teng guess that the thieves would also steal q times of crops. he also guessed the range they were going to steal, which was also a rectangle. Xiao Teng wants to know if his monitors can see all the thieves at a time.

Input

There are mutiple test cases.
Each case starts with a line containing two integers n,m(1≤n,1≤m,n×m≤107) which represent the area of the land.
And the secend line contain a integer p(1≤p≤106) which represent the number of the monitor Xiaoteng has installed. This is followed by p lines each describing a rectangle. Each of these lines contains four intergers x1,y1,x2 and y2(1≤x1≤x2≤n,1≤y1≤y2≤m) ,meaning the lower left corner and upper right corner of the rectangle.
Next line contain a integer q(1≤q≤106) which represent the number of times that thieves will steal the crops.This is followed by q lines each describing a rectangle. Each of these lines contains four intergers x1,y1,x2 and y2(1≤x1≤x2≤n,1≤y1≤y2≤m),meaning the lower left corner and upper right corner of the rectangle.

Output

For each case you should print q lines.
Each line containing YES or NO mean the all thieves whether can be seen.

Sample Input

6 6
3
2 2 4 4
3 3 5 6
5 1 6 2
2
3 2 5 4
1 5 6 5

Sample Output

YES
NO

Hint

In the picture,the red solid rectangles mean the monitor Xiaoteng installed, and the blue dotted rectangles mean the area will be stolen.

(x1,y1)为矩形左下角,(x2,y2)为矩形右下角,竖直向上为x正方向,水平向右为y正方向

题意:

在一个面积不超过n*m的矩形上,有p个矩形A,问之后的q个矩形B能否被之前的A全部覆盖。

思路:

由于n*m,p,q的范围过大,于是考虑O(n*m+p+q)的做法,即二维前缀和+差分。

对于A类矩形(x1,y1,x2,y2),我们只需要在(x1,y1),(x2+1,y2+1)处+1,在(x1,y2+1),(x2+1,y1)处-1 ,

之后对整个面积求一个前缀和,则大于0的地方就是被A类矩形覆盖的点。

把值大于0的地方变成1,再一次求一次前缀和,处理好后即可在O(1)的时间算出一个矩形内被覆盖的点的数量。
(详细见注释)

亮点:

二维数组化为一维

两次求前缀和,重新赋值

代码如下:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <iostream>
 4 #include <string>
 5 #include <math.h>
 6 #include <algorithm>
 7 #include <vector>
 8 #include <stack>
 9 #include <queue>
10 #include <set>
11 #include <map>
12 #include <math.h>
13 const int INF=0x3f3f3f3f;
14 typedef long long LL;
15 const int mod=1e9+7;
16 //const double PI=acos(-1);
17 const int maxn=1e7+10;
18 using namespace std;
19
20 int a[maxn];//二维化为一维
21 int n,m;
22
23 void Add(int x,int y,int val)//添加标记
24 {
25     if(x>n||y>m)
26         return;
27     a[(x-1)*m+y]+=val;
28 }
29
30 int Query(int x,int y)//得到该处的值,主要用来处理边界0
31 {
32     if(x==0||y==0)
33         return 0;
34     return a[(x-1)*m+y];
35 }
36
37 void Sum()//求前缀和
38 {
39     for(int i=1;i<=n;i++)
40     {
41         for(int j=1;j<=m;j++)
42         {
43             a[(i-1)*m+j]+=Query(i,j-1)+Query(i-1,j)-Query(i-1,j-1);
44         }
45     }
46 }
47
48 int main()
49 {
50     while(~scanf("%d %d",&n,&m))
51     {
52         memset(a,0,sizeof(a));
53         int x1,x2,y1,y2;
54         int p,q;
55         scanf("%d",&p);
56         while(p--)
57         {
58             scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
59             Add(x1,y1,1);
60             Add(x2+1,y2+1,1);
61             Add(x1,y2+1,-1);
62             Add(x2+1,y1,-1);
63         }
64         Sum();//第一次求二维前缀和,a[i]>0说明该处被覆盖过
65         for(int i=1;i<=n;i++)//将被覆盖的点重新赋值为1,便于判断
66         {
67             for(int j=1;j<=m;j++)
68             {
69                 if(a[(i-1)*m+j])
70                     a[(i-1)*m+j]=1;
71             }
72         }
73         Sum();//第二次求前缀和,得到的结果即为矩形内被染色的面积
74         scanf("%d",&q);
75         while(q--)
76         {
77             scanf("%d %d %d %d",&x1,&y1,&x2,&y2);
78             int ans=Query(x2,y2)-Query(x1-1,y2)-Query(x2,y1-1)+Query(x1-1,y1-1);//利用前缀和得出矩形内被染色的面积
79             if(ans==(x2-x1+1)*(y2-y1+1))//看染色的面积是否等于矩形的总面积
80                 printf("YES\n");
81             else
82                 printf("NO\n");
83         }
84     }
85     return 0;
86 }

原文地址:https://www.cnblogs.com/jiamian/p/11524051.html

时间: 2024-10-09 00:12:11

HDU-6514 Monitor(二维前缀和+差分)的相关文章

二维前缀和差分+离散化

/* 二维前缀和求法 a[i][j]+=a[i][j-1]+a[i-1][j]-a[i-1][j-1]; 构建前缀和 int n,m; scanf("%d%d",&n,&m); for(int i=1;i<=n;i++){//初始化 for(int j=1;j<=m;j++){ int x; scanf("%d",&x); a[i][j]+=a[i][j-1]+a[i-1][j]-a[i-1][j-1]+x; } } 输入nm 以

杭电2018多校第四场(2018 Multi-University Training Contest 4) 1005.Problem E. Matrix from Arrays (HDU6336) -子矩阵求和-规律+二维前缀和

6336.Problem E. Matrix from Arrays 不想解释了,直接官方题解: 队友写了博客,我是水的他的代码 ------>HDU 6336 子矩阵求和 至于为什么是4倍的,因为这个矩阵是左上半边有数,所以开4倍才能保证求的矩阵区域里面有数,就是图上的红色阴影部分,蓝色为待求解矩阵. 其他的就是容斥原理用一下,其他的就没什么了. 代码: 1 //1005-6336-矩阵求和-二维前缀和+容斥-预处理O(1)查询输出 2 #include<iostream> 3 #in

二维前缀和好题hdu6514

#include<bits/stdc++.h> #define rep(i,a,b) for(int i=a;i<=b;i++) using namespace std; int n,m,a[20000007]; void add(int i,int j,int val){a[(i-1)*m+j]+=val;} int q(int i,int j) { if(i==0||j==0) return 0; return a[(i-1)*m+j]; } int main(){ int p,Q;

openjudge1768 最大子矩阵[二维前缀和or递推|DP]

总时间限制:  1000ms 内存限制:  65536kB 描述 已知矩阵的大小定义为矩阵中所有元素的和.给定一个矩阵,你的任务是找到最大的非空(大小至少是1 * 1)子矩阵. 比如,如下4 * 4的矩阵 0 -2 -7 09 2 -6 2-4 1 -4 1-1 8 0 -2 的最大子矩阵是 9 2-4 1-1 8 这个子矩阵的大小是15. 输入 输入是一个N * N的矩阵.输入的第一行给出N (0 < N <= 100).再后面的若干行中,依次(首先从左到右给出第一行的N个整数,再从左到右给

Good Bye 2015 C. New Year and Domino 二维前缀

C. New Year and Domino They say "years are like dominoes, tumbling one after the other". But would a year fit into a grid? I don't think so. Limak is a little polar bear who loves to play. He has recently got a rectangular grid with h rows and w

计蒜客模拟赛D1T1 蒜头君打地鼠:矩阵旋转+二维前缀和

题目链接:https://nanti.jisuanke.com/t/16445 题意: 给你一个n*n大小的01矩阵,和一个k*k大小的锤子,锤子只能斜着砸,问只砸一次最多能砸到多少个1. 题解: 将原矩阵顺时针旋转45°,二维前缀和预处理,然后枚举每一个可能砸到的正方形之和并取最大. 注:枚举的正方形的四个顶点必须是从原矩阵璇转过来的点,代码中用vis数组判断. #include <iostream> #include <stdio.h> #include <string.

弱校联盟10.7 I. Special Squares(二维前缀和)

题目链接: I. Special Squares There are some points and lines parellel to x-axis or y-axis on the plane. If arbitrary chosen two lines parallel to x-axis and two lines parallel to y-axis, one rectangle, or sometimes a square, will be formed. If a square i

CDOJ 1256 二维前缀和处理

昊昊喜欢运动 他NN 天内会参加MM 种运动(每种运动用一个[1,m][1,m] 的整数表示) 舍友有QQ 个问题 问昊昊第ll 天到第rr 天参加了多少种不同的运动 Input 输入两个数NN , MM (1≤N≤20001≤N≤2000 , 1≤M≤1001≤M≤100 ); 输入NN 个数aiai 表示在第i天昊昊做了第aiai 类型的运动; 输入一个数QQ (1≤Q≤1061≤Q≤106 ); 输入QQ 行 每行两个数 ll , rr (1≤l≤r≤n1≤l≤r≤n ); Output

二维前缀和 - 算法学习 - 输入输出优化

2017-08-27 11:11:38 writer:pprp 二维前缀和主要用到了容斥定理,具体实现还是有点复杂的 详见代码: /* @theme:二维前缀和 @writer:pprp @declare:用到容斥定理 @date:2017/8/27 */ #include <bits/stdc++.h> using namespace std; const int maxn = 1010; int n, m, a[maxn][maxn]; //输入优化 inline int read() {