题意:给出一张地图,一个n * m的方格图。
给出K个监督者的位置,每个监督者可以监视他所处的行和列上的每一格位置。
一个区域被认为是安全的,当且仅当区域中的每一个方格都被监督者监视着。(区域外的监督者无法监视这个区域中的方格)
现在你需要回答q次询问。
每次询问包含四个数字x1 y1 x2 y2表示区域的左上角方格的坐标,右下角方格的坐标。
如果询问区域是安全的,那么输出"YES",否则输出"NO"。
分析:因为数据范围很大,不能暴力预处理。因此,需要考虑别的算法,比如数据结构,我们考虑能否优化成(o(nlogn))之类的算法,对于一个区域,我们要想这个区域内的每行每列都被监视到,可以从不同的方面考虑,把行和列分开来考虑,我们把骑士的x坐标从小到大排序,直到骑士的x坐标<= 当前询问的右下角x2坐标,再用一个数据结构维护y轴,每个点上再维护插入的骑士的x坐标的最小值,这样,当我们查询一个范围内([y1, y2])的最小值时,如果这个最小值>=x1,那么这个区间的每行每列都会被监视到。(为什么不需要判断<=x2这种情况呢),因为我们是从小到大单点修改的,如果这个点没有被修改过,那么整个区间的最小值就会=0。我们还要考虑翻转x轴和y轴的情况,这个可以画图,我们只要满足两者之一即可。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <algorithm>
using namespace std;
const int N = 200005;
const int M = 100005;
const int inf = 0x3f3f3f3f;
struct Node
{
int x, y;
}kni[N];
struct query
{
int x1, y1, x2, y2;
int id;
}que[N];
int res[N];
int n, m, k, q;
bool cmp(const Node& lhs, const Node& rhs)
{
return lhs.x < rhs.x;
}
bool cmp1(const query& lhs, const query& rhs)
{
return lhs.x2 < rhs.x2;
}
struct seg
{
int val;
}tr[M * 4];
void modify(int u, int l, int r, int pos, int val)
{
if (l == r)
{
tr[u].val = val;
return;
}
int mid = l + r >> 1;
if (pos <= mid) modify(u << 1, l, mid, pos, val);
else modify(u << 1 | 1, mid + 1, r, pos, val);
tr[u].val = min(tr[u << 1].val, tr[u << 1 | 1].val);
}
int Query(int u, int L, int R, int l, int r)
{
if (l <= L && r >= R)
{
return tr[u].val;
}
int mid = L + R >> 1;
int res = inf;
if (l <= mid) res = min(res, Query(u << 1, L, mid, l, r));
if (r > mid) res = min(res, Query(u << 1 | 1, mid + 1, R, l, r));
return res;
}
void cal()
{
memset(tr, 0, sizeof tr);
int cnt = 0;
for (int i = 1; i <= q; ++i)
{
while (cnt <= k && kni[cnt].x <= que[i].x2)
{
modify(1, 1, m, kni[cnt].y, kni[cnt].x);
++cnt;
}
if (Query(1, 1, m, que[i].y1, que[i].y2) >= que[i].x1)
res[que[i].id] = 1;
}
}
void Swap()
{
swap(n, m);
for (int i = 1; i <= k; ++i)
swap(kni[i].x, kni[i].y);
sort(kni + 1, kni + k + 1, cmp);
for (int i = 1; i <= q; ++i)
{
swap(que[i].x1, que[i].y1);
swap(que[i].x2, que[i].y2);
}
sort(que + 1, que + q + 1, cmp1);
}
int main()
{
scanf("%d%d%d%d", &n, &m, &k, &q);
//int x, y;
for (int i = 1; i <= k; ++i)
{
scanf("%d%d", &kni[i].x, &kni[i].y);
}
sort(kni + 1, kni + k + 1, cmp);
for (int i = 1; i <= q; ++i)
{
scanf("%d%d%d%d", &que[i].x1, &que[i].y1, &que[i].x2, &que[i].y2);
que[i].id = i;
}
sort(que + 1, que + q + 1, cmp1);
cal();
Swap();
cal();
for (int i = 1; i <= q; ++i)
{
if (res[i] == 1)
puts("YES");
else
puts("NO");
}
return 0;
}