给出n个点和一个矩形的长和宽, 问这个矩形最多能覆盖多少个点。
矩形放的最优方案一定存在一种是左边界或者右边界上有点,假设是左边界上有点, 就可以枚举左边界上的是哪个点, 也就是从左向右扫, 假设扫到了第i个点, 那么在第i个点右边并且x坐标距离小于w的点j, 如果矩形的上边界在a[j].y 和a[j].y + h之间的话, 那么矩形就可以覆盖这个点, 所以每个点都是对a[j].y 和a[j].y + h这段区间加1, 然后答案就是整个区间的最大值, 用线段树维护就可以了。。
#include <iostream>
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
#define mnx 10020
#define inf 0x3f3f3f3f
#define ls (i << 1)
#define rs (ls | 1)
#define md ((ll + rr) >> 1)
int n, w, h;
struct point {
int x, y;
bool operator < (const point &b) const {
if(x != b.x) return x < b.x;
return y < b.y;
}
}a[mnx];
int san[mnx * 2], cnt;
int haxi(int x) {
return lower_bound(san + 1, san + cnt + 1, x) - san;
}
int mx[mnx * 8], add[mnx * 8];
void build(int ll, int rr, int i) {
mx[i] = add[i] = 0;
if(ll == rr) return;
build(ll, md, ls), build(md + 1, rr, rs);
}
void down(int i) {
if(add[i]) {
mx[ls] += add[i], mx[rs] += add[i];
add[ls] += add[i], add[rs] += add[i];
add[i] = 0;
}
}
void update(int l, int r, int v, int ll, int rr, int i) {
if(ll == l && rr == r) {
mx[i] += v;
add[i] += v;
return;
}
down(i);
if(r <= md) update(l, r, v, ll, md, ls);
else if(l > md) update(l, r, v, md + 1, rr, rs);
else update(l, md, v, ll, md, ls),
update(md + 1, r, v, md + 1, rr, rs);
mx[i] = max(mx[ls], mx[rs]);
}
int main() {
while(scanf("%d%d%d", &n, &w, &h) && n > 0) {
cnt = 0;
for(int i = 1; i <= n; ++i) {
scanf("%d%d", &a[i].x, &a[i].y);
san[++cnt] = a[i].y;
san[++cnt] = a[i].y + h;
}
sort(a + 1, a + n + 1);
sort(san + 1, san + cnt + 1);
cnt = unique(san + 1, san + cnt + 1) - san - 1;
int j = 1;
int ans = 0;
build(1, cnt, 1);
for(int i = 1; i <= n; ++i) {
while(j <= n && a[j].x <= a[i].x + w) {
int u = a[j].y;
int v = a[j].y + h;
u = haxi(u), v = haxi(v);
update(u, v, 1, 1, cnt, 1);
++j;
}
ans = max(ans, mx[1]);
int u = a[i].y;
int v = a[i].y + h;
u = haxi(u), v = haxi(v);
update(u, v, -1, 1, cnt, 1);
}
printf("%d\n", ans);
}
return 0;
}