线段树。
题意:平面上有许多点,每个点有一个权值。给定一个大小确定的矩形,边与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;
}