题目链接:
http://poj.org/problem?id=2482
题意:
在一个平面上给出许多星星的坐标,每个星星有一个权值。
求用长宽分别为w,h的矩形圈住的星星的权值最大为?(矩形横着放)。
思路:
一个矩形的位置可以由右上角的坐标确定下来。如果要围住一个星星,
那么这个矩形的右上角一定在以该星星为左下角长宽为w,h的矩形内。
以每个星星构造一个矩形,每个矩形有一个权值。即求一个坐标在这些矩形中权值和最大。
借助扫描线,用线段树维护单点最大值即可。线段树需用延迟标记。
代码:
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long ll;
const int maxn=10000;
int n,w,h;
struct Point
{
int x,y,c;
};
struct Line
{
bool operator<(const Line &t)const{return x<t.x;}
ll x;
int y1,y2,c;
};
Point place[maxn];
Line line[maxn*2];
ll y[maxn*2];
int tag[maxn*2*4];
int ma[maxn*2*4];
void change(int c,int a,int b,int k,int l,int r)
{
if(a<=l&&b>=r)
{
tag[k]+=c;
ma[k]+=c;
}
else
{
int m=(l+r)>>1;
if(a<m)change(c,a,b,2*k+1,l,m);
if(b>m)change(c,a,b,2*k+2,m,r);
ma[k]=max(ma[2*k+1],ma[2*k+2])+tag[k];
}
}
int main()
{
while(~scanf("%d%d%d",&n,&w,&h))
{
int cy=0;
for(int i=0;i<n;++i)
{
scanf("%d%d%d",&place[i].x,&place[i].y,&place[i].c);
y[cy++]=place[i].y;
y[cy++]=(ll)place[i].y+h-1;
}
sort(y,y+cy);
cy=unique(y,y+cy)-y;
int cl=0;
for(int i=0;i<n;++i)
{
line[cl].x=place[i].x;
line[cl].c=place[i].c;
line[cl].y1=lower_bound(y,y+cy,(ll)place[i].y)-y;
line[cl++].y2=lower_bound(y,y+cy,(ll)place[i].y+h-1)-y;
line[cl]=line[cl-1];
line[cl].x+=w;
line[cl].c=-line[cl].c;
++cl;
}
memset(tag,0,sizeof(tag));
memset(ma,0,sizeof(ma));
sort(line,line+cl);
int ans=0;
for(int i=0;i<cl;++i)
{
change(line[i].c,line[i].y1,line[i].y2+1,0,0,cy+1);
ans=max(ans,ma[0]);
}
printf("%d\n",ans);
}
return 0;
}