一.题目链接:
HDU-6514
二.题目大意:
给你 p 个红矩阵
一个整数 q,接下来 q 行
每行给出一个蓝矩阵
如果蓝矩阵被完全包含于红矩阵内,输出 "YES",否则输出 "NO".
三.分析:
赛后听 ltr 讲才恍然大悟,不就是这两道题的结合吗?(tql orzzzz)
最大子矩阵(HDU - 1559,前缀和)
Color the ball(HDU - 1556,前缀和)
其实就是利用 前缀和处理 + 矩阵和 算出哪些区域是被红矩形标记过的
之后将标记过的点置为 1 ,再来一次前缀和.
之后 O(1) 查询蓝矩阵的子矩阵和即可.
四.代码实现:
#include <set>
#include <map>
#include <ctime>
#include <queue>
#include <cmath>
#include <stack>
#include <vector>
#include <cstdio>
#include <sstream>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#define eps 1e-6
#define pi acos(-1.0)
#define ll long long int
using namespace std;
const int M = (int)1e7;
vector < vector<int> > mp;
vector < vector<int> > sum;
void init(int n, int m)
{
mp.clear();
sum.clear();
mp.resize(n + 5);
sum.resize(n + 5);
for(int i = 0; i < n + 5; ++i)
{
mp[i].clear();
sum[i].clear();
mp[i].resize(m + 5);
sum[i].resize(m + 5);
}
}
void get_sum(int n, int m)
{
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= m; ++j)
{
sum[i][j] = sum[i][j - 1] + sum[i - 1][j] - sum[i - 1][j - 1] + mp[i][j];
}
}
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= m; ++j)
{
if(sum[i][j])
mp[i][j] = 1;
else
mp[i][j] = 0;
sum[i][j] = 0;
}
}
for(int i = 1; i <= n; ++i)
{
for(int j = 1; j <= m; ++j)
{
sum[i][j] = sum[i][j - 1] + sum[i - 1][j] - sum[i - 1][j - 1] + mp[i][j];
}
}
}
int main()
{
int n, m;
while(~scanf("%d %d", &n, &m))
{
init(n, m);
int p;
scanf("%d", &p);
while((p--) > 0)
{
int x1, y1, x2, y2;
scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
swap(x1, x2);
x1 = n - x1 + 1;
x2 = n - x2 + 1;
mp[x1][y1]++;
mp[x2 + 1][y2 + 1]++;
mp[x1][y2 + 1]--;
mp[x2 + 1][y1]--;
}
get_sum(n, m);
int q;
scanf("%d", &q);
while((q--) > 0)
{
int x1, y1, x2, y2;
scanf("%d %d %d %d", &x1, &y1, &x2, &y2);
swap(x1, x2);
x1 = n - x1 + 1;
x2 = n - x2 + 1;
int ans = sum[x2][y2] - sum[x1 - 1][y2] - sum[x2][y1 - 1] + sum[x1 - 1][y1 - 1];
int area = (x2 - x1 + 1) * (y2 - y1 + 1);
if(ans == area)
puts("YES");
else
puts("NO");
}
}
return 0;
}