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(1n,1m,n×m107) which represent the area of the land.
And the secend line contain a integer p(1p106) 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(1x1x2n,1y1y2m) ,meaning the lower left corner and upper right corner of the rectangle.
Next line contain a integer q(1q106) 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(1x1x2n,1y1y2m),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
");
81             else
82                 printf("NO
");
83         }
84     }
85     return 0;
86 }
原文地址:https://www.cnblogs.com/jiamian/p/11524051.html