题目链接:点击查看
题意:给你n个点的坐标,给你一个矩形的w,h,问最多能圈住多少点
题解:扫描线,按x轴进行扫描,其实就是把一个点的左右范围找出来,一个为正,一个为负,把y对应的区间更新一下即可,我对y离散化了一下,其实不离散化也行,我们吧初始都加为正,y最多80000,时间也差不多。
#include <bits/stdc++.h>
using namespace std;
const int N = 80010;
struct node {
int l, r;
int val,laz;
}tree[N << 2];
struct Point {
int x, y1, y2;
int val;
}p[20010];
int n, w, h;
int b[20010];
int cmp(Point x,Point y)
{
if(x.x!=y.x)return x.x<y.x;
else return x.val>y.val;
}
void build(int l,int r,int cur)
{
tree[cur].l=l;
tree[cur].r=r;
tree[cur].val=0;
tree[cur].laz=0;
if(l==r)return;
int mid=(l+r)>>1;
build(l,mid,cur<<1);
build(mid+1,r,cur<<1|1);
}
void pushup(int cur)
{
tree[cur].val=max(tree[cur<<1].val,tree[cur<<1|1].val);
}
void pushdown(int cur)
{
if(tree[cur].laz)
{
tree[cur<<1].laz+=tree[cur].laz;
tree[cur<<1].val+=tree[cur].laz;
tree[cur<<1|1].val+=tree[cur].laz;
tree[cur<<1|1].laz+=tree[cur].laz;
tree[cur].laz=0;
}
}
void update(int pl,int pr,int cur,int val)
{
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
tree[cur].val+=val;
tree[cur].laz+=val;
return;
}
pushdown(cur);
int mid=(tree[cur].l+tree[cur].r)>>1;
if(pl<=mid) update(pl,pr,cur<<1,val);
if(pr>mid) update(pl,pr,cur<<1|1,val);
pushup(cur);
}
int main() {
int x, y;
int y1,y2;
while(~scanf("%d", &n)) {
if(n < 0) break;
scanf("%d %d", &w, &h);
for(int i = 1; i <= n; i++) {
scanf("%d %d", &x,&y);
p[i*2-1].x=x+20001;
p[i*2-1].y1=y+20001;
p[i*2-1].y2=y+20001+h;
p[i*2-1].val=1;
p[i*2].x=x+20001+w;
p[i*2].y1=y+20001;
p[i*2].y2=y+20001+h;
p[i*2].val=-1;
b[i*2-1]=y+20001;
b[i*2]=y+20001+h;
}
sort(p+1,p+1+n*2,cmp);
sort(b+1,b+1+n*2);
int len=unique(b+1,b+1+n*2)-(b+1);
build(1,len,1);
int ans=0;
for(int i=1;i<=n*2;i++)
{
y1=lower_bound(b+1,b+1+len,p[i].y1)-b;
y2=lower_bound(b+1,b+1+len,p[i].y2)-b;
update(y1,y2,1,p[i].val);
ans=max(ans,tree[1].val);
}
printf("%d\n",ans);
}
return 0;
}