线段树。
题意:平面上有许多点,每个点有一个权值。给定一个大小确定的矩形,边与x,y轴平行,平移这个矩形能圈住的点的权值之和最大是多少。
注意:矩形边上的不算,所以应该把矩形缩小一点。数据范围会超int,建议用long long
做法:
先把题目转化一下,用矩形的中心点来描述这个矩形的位置。并对每个点建立一个矩形中心点的活动范围,即矩形中心点在这个范围内即可覆盖到该点,建立方法就是以每个点为中心画一个与题中矩形大小相等的矩形。现在点变成了矩形,矩形变成了点。我们要求的是找一个位置来放这个点使得它在最多的矩形内部,即该点的矩形重叠层数最多。
这样我们就可以用线段树来解决了,用一条与y轴平行的扫描线,从左到右来扫描这个矩形重叠图。这条扫描线就是线段树中的整条线段区间,在一个时刻这个线段的不同位置被覆盖了不同层数的矩形,对每次扫描线产生变化后(扫入某一矩形或扫出某一矩形后)求现在正在扫的矩形在线段上覆盖的最大层数。
代码:
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; #define maxn 110000 #define LL long long struct list { LL l,r,x,val; } node[maxn*6]; struct liss { LL x; LL y1,y2; LL c,val; } line[maxn*2]; LL lines; LL yy[maxn]; LL a[maxn],b[maxn],c[maxn]; LL sk; LL n,W,H; LL maxx; int cmp(struct liss a,struct liss b) { if(a.x!=b.x)return a.x<b.x; return a.val>b.val; } LL search(LL x) { LL l=0; LL r=sk; LL mid=(l+r)/2; while(l<r) { if(yy[mid]==x)return mid; if(yy[mid]>x)r=mid; if(yy[mid]<x)l=mid+1; mid=(l+r)/2; } } void build(LL l,LL r,int st) { LL mid=(l+r)/2; node[st].l=l; node[st].r=r; node[st].x=0; node[st].val=0; if(l!=r) { build(l,mid,st*2); build(mid+1,r,st*2+1); } } void insert(LL l,LL r,LL val,int st) { LL ll=node[st].l; LL rr=node[st].r; if(l>rr||r<ll)return; if(l<=ll&&rr<=r) { node[st].x+=val; node[st].val+=val; return ; } insert(l,r,val,st*2); insert(l,r,val,st*2+1); node[st].val=max(node[st*2].val,node[st*2+1].val)+node[st].x; } int main() { LL i; while(~scanf("%lld%lld%lld",&n,&W,&H)) { LL sy=0; LL yy1,yy2,xx1,xx2; for(i=0; i<n; i++) { scanf("%lld%lld%lld",&a[i],&b[i],&c[i]); yy1=b[i]; yy[sy++]=yy1; yy2=b[i]+H-1; yy[sy++]=yy2; } if(W==0||H==0) { cout<<"0"<<endl; continue; } H--,W--; sort(yy,yy+sy); sk=1; for(i=1; i<sy; i++)if(yy[i]!=yy[i-1])yy[sk++]=yy[i]; lines=0; for(i=0; i<n; i++) { yy2=b[i]+H; yy1=b[i]; xx2=a[i]+W; xx1=a[i]; yy1=search(yy1); yy2=search(yy2); line[lines].x=xx1; line[lines].y1=yy1; line[lines].y2=yy2; line[lines++].val=c[i]; line[lines].x=xx2; line[lines].y1=yy1; line[lines].y2=yy2; line[lines++].val=-c[i]; } sort(line,line+lines,cmp); build(0,sk,1); maxx=0; for(i=0; i<lines; i++) { insert(line[i].y1,line[i].y2,line[i].val,1); maxx=max(maxx,node[1].val); } cout<<maxx<<endl; } return 0; }