题目链接:
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; }