关于这道题的知识:https://blog.csdn.net/k_r_forever/article/details/81775899
本题解 思路来源:https://blog.csdn.net/LSD20164388/article/details/89412548
题意:给你长为m高为n的一个矩形区域种了西瓜(先假装是西瓜),你有p个监视器,可以监视p个不同大小的矩形区域。有q群坏蛋来偷西瓜,每次偷一个矩形的西瓜。问你每个矩阵里的坏蛋能不能全被监视器看到。
思路:看到这么多矩形,第一反应是扫描线,然而不是,是一个叫二维前缀和的东西。。。关于二维前缀和 可以看第一个链接。思路实现比较简单,就是一个差分的模板题:
0、首先这个题,我们只知道n和m乘积的最大值,而若n和m都取最大值显然会爆掉,然而题目给的n和m乘积的最大值却不会爆掉。所以我们可以用一维数组来表示二维数组。
1、对于每个加入的点矩形,我们把它的四个顶点进行差分处理。如下:
void add(int x,int y,int v) {
if(id(x,y)==0) return;//防止越界下标
a[id(x,y)]+=v;
}
add( x1, y1, 1);
add(x2+1,y2+1, 1);
add( x1,y2+1,-1);
add(x2+1, y1,-1);
2、三次核心处理,就可以了:
for(int i=1; i<=n; i++) {//第一次 用差分来处理数组,
for(int j=1; j<=m; j++) {//使其变成当前点被覆盖过的次数。
a[id(i,j)]+=(a[id(i-1,j)]+a[id(i,j-1)]-a[id(i-1,j-1)]);
}
}
for(int i=1; i<=n; i++) {//第二次,忽略覆盖次数 只要覆盖了就算做一次
for(int j=1; j<=m; j++) {
a[id(i,j)]=(a[id(i,j)]>0);
}
}
for(int i=1; i<=n; i++) {//第三次,求出答案
for(int j=1; j<=m; j++) {
a[id(i,j)]+=(a[id(i-1,j)]+a[id(i,j-1)]-a[id(i-1,j-1)]);
}
}
下面是AC代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define ll long long
#define inf 0x3f3f3f3f
#define cl(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=1e7+10;
int n,m,p,q;
int a[maxn];
int id(int x,int y) {
if(x<1||y<1||x>n||y>m) return 0;
return (x-1)*m+y;//这里还要乘以m!!!你个zz
}
void add(int x,int y,int v) {
if(id(x,y)==0) return;//防止越界下标
a[id(x,y)]+=v;
}
int main() {
while(scanf("%d%d",&n,&m)!=EOF) {
for(int i=1;i<=n;i++){
for(int j=1;j<=m;j++){
a[id(i,j)]=0;
}
}
cin>>p;
for(int i=1; i<=p; i++) {
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
add( x1, y1, 1);
add(x2+1,y2+1, 1);
add( x1,y2+1,-1);
add(x2+1, y1,-1);
}
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
a[id(i,j)]+=(a[id(i-1,j)]+a[id(i,j-1)]-a[id(i-1,j-1)]);
}
}
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
a[id(i,j)]=(a[id(i,j)]>0);
}
}
for(int i=1; i<=n; i++) {
for(int j=1; j<=m; j++) {
a[id(i,j)]+=(a[id(i-1,j)]+a[id(i,j-1)]-a[id(i-1,j-1)]);
}
}
int q;
cin>>q;
for(int i=1; i<=q; i++) {
int x1,y1,x2,y2;
scanf("%d%d%d%d",&x1,&y1,&x2,&y2);
int sum0=(x2-x1+1)*(y2-y1+1);
//sum1写错了!!!
int sum1=a[id(x2,y2)]+a[id(x1-1,y1-1)]-a[id(x1-1,y2)]-a[id(x2,y1-1)];
if(sum0==sum1) printf("YES\n");
else printf("NO\n");
}
}
return 0;
}
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.