http://acm.hdu.edu.cn/showproblem.php?pid=5091
把所有点的纵坐标打入到x轴上的对应位置上 然后双指针i-w-1和i向后扫过去 一个减一个加
减或加指的就是 假设该点纵坐标为y 矩形高度为h 就将[Y,Y+H]区间的最大值减或加1 然后用tree[1].val更新答案
这时线段树每个叶子节点维护的值的含义就不再是对应高度有多少个点了 而是将给定矩形的上边界顶在该高度上 向下可以覆盖多少个点(左右边界通过双指针枚举)
#include <bits/stdc++.h>
using namespace std;
struct node
{
int l;
int r;
int val;
int laz;
};
vector <int> point[40010];
node tree[160010];
int n,w,h;
void pushup(int cur)
{
tree[cur].val=max(tree[2*cur].val,tree[2*cur+1].val);
}
void pushdown(int cur)
{
if(tree[cur].laz!=0)
{
tree[2*cur].val+=tree[cur].laz;
tree[2*cur].laz+=tree[cur].laz;
tree[2*cur+1].val+=tree[cur].laz;
tree[2*cur+1].laz+=tree[cur].laz;
tree[cur].laz=0;
}
}
void build(int l,int r,int cur)
{
int m;
tree[cur].l=l;
tree[cur].r=r;
tree[cur].val=0;
tree[cur].laz=0;
if(l==r) return;
m=(l+r)/2;
build(l,m,2*cur);
build(m+1,r,2*cur+1);
}
void update(int pl,int pr,int val,int cur)
{
if(pl<=tree[cur].l&&tree[cur].r<=pr)
{
tree[cur].val+=val;
tree[cur].laz+=val;
return;
}
pushdown(cur);
if(pl<=tree[2*cur].r) update(pl,pr,val,2*cur);
if(pr>=tree[2*cur+1].l) update(pl,pr,val,2*cur+1);
pushup(cur);
}
int main()
{
int i,j,x,y,pos,ans;
while(scanf("%d",&n)!=EOF)
{
if(n==-1) break;
scanf("%d%d",&w,&h);
for(i=0;i<=40000;i++)
{
point[i].clear();
}
for(i=1;i<=n;i++)
{
scanf("%d%d",&x,&y);
x+=20000,y+=20000;
point[x].push_back(y);
}
build(0,40000,1);
for(i=0;i<=w;i++)
{
for(j=0;j<point[i].size();j++)
{
pos=point[i][j];
update(pos,min(40000,pos+h),1,1);
}
}
ans=tree[1].val;
for(;i<=40000;i++)
{
for(j=0;j<point[i-w-1].size();j++)
{
pos=point[i-w-1][j];
update(pos,min(40000,pos+h),-1,1);
}
for(j=0;j<point[i].size();j++)
{
pos=point[i][j];
update(pos,min(40000,pos+h),1,1);
}
ans=max(ans,tree[1].val);
}
printf("%d\n",ans);
}
return 0;
}