题意:给出一张地图,一个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;
}