题目链接
题目大意: 在平面内有一些点,现在给定一个矩形框,求矩形框能包含最多点的个数。
分析: 可以转化成一维的线段树。先确定横坐标的范围,这样只需要找满足纵坐标最大的差小于等于矩形框的高的最多的点就行了。把纵坐标做成线段树,以每个点的纵坐标为起点,长度为矩形框的高在线段树上覆盖。如果有两个线段覆盖了同一段区域,那么说明可以找到一个矩形同时覆盖这两个点。所以题目转化成了找线段树中最大的线段覆盖数。
代码:
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cstdlib> #include <vector> #include <queue> #include <deque> #include <stack> #include <set> #include <cmath> using namespace std; const int maxn = 4e4 + 5; const int maxm = 1e4 + 5; #define lson l, m, v << 1 #define rson m + 1, r, v << 1 | 1 struct Node { int x, y; bool operator <(const Node &rhs) const { return x < rhs.x; } }node[maxm]; int sum[maxn << 2], col[maxn << 2]; void PushUp(int v) { sum[v] = max(sum[v << 1], sum[v << 1 | 1]); } void PushDown(int v, int len) { if (col[v]) { col[v << 1] += col[v]; col[v << 1 | 1] += col[v]; sum[v << 1] += col[v]; sum[v << 1 | 1] += col[v]; col[v] = 0; } } void update(int L, int R, int x, int l, int r, int v) { if (L <= l && r <= R) { sum[v] += x; col[v] += x; return; } int m = (l + r) >> 1; PushDown(v, r - l + 1); if (L <= m) update(L, R, x, lson); if (R > m) update(L, R, x, rson); PushUp(v); } int query(int L, int R, int l, int r, int v) { if (L <= l && r <= R) return sum[v]; int ans = 0; PushDown(v, r - l + 1); int m = (l + r) >> 1; if (L <= m) ans = max(ans, query(L, R, lson)); if (R > m) ans = max(ans, query(L, R, rson)); return ans; } int n, xx, yy; int main() { while (~scanf("%d", &n) && n > 0) { memset(sum, 0, sizeof(sum)); memset(col, 0, sizeof(col)); scanf("%d%d", &xx, &yy); for (int i = 1; i <= n; i ++) scanf("%d%d", &node[i].x, &node[i].y); sort(node + 1, node + n + 1); int q = 1; int ans = 0; for (int p = 1; p <= n; p ++) { while (q <= n && node[q].x <= node[p].x + xx) { update(node[q].y + 20000, node[q].y + yy + 20000, 1, 0, 40000, 1); q ++; } ans = max(ans, query(0, 40000, 0, 40000, 1)); update(node[p].y + 20000, node[p].y + yy + 20000, -1, 0, 40000, 1); } printf("%d\n", ans); } return 0; }