题目:
题意:
假定天空是一个平面,每个星星都有一个坐标(x,y),每颗星星都有一个亮度C,代表它的亮度。窗户是长方形的,有固定的长和宽,边平行于x轴和y轴。你的任务是告诉我如何摆放窗户,才能获得在窗口内所有星星的亮度总和最大值。注意,边框的星星不算。窗口可以被平移,但不允许旋转。
输入
在输入中有几个测试样例例。每一行的第一行包含3个整数:n,w,h,表示星形的数目,矩形窗口的水平长度和垂直高度。然后N行如下,有3个整数分别为:X,Y,C,表示星星位置(x,y)和每个恒星的亮度。没有两颗星星在同一点上。
天空中至少有1颗,最多有10000颗星星。1 = < W,h <= 1000000,0 =< x,y ,C < 2^31。
输出
对于每个测试样例,输出窗口内所有星星的亮度总和最大值。
题解:
原来只要转换一下,就能把其转换为求线段区间的最大值,每个星星所能影响的范围[(x,y),(x+w-1,y+h-1)]且有一权值,它们重合就表示能被这个矩形框在一起,也就是说,只要求出重合的矩形的权值最大就行了。
以x从小到大排序,y值离散化,投影到y轴上,那么对于每个星星的纵坐标,y,y+h-1就是每个星星可以影响到的矩形 然后x,x+w-1就是一个进入事件和一个出去事件,其所带的值互为相反数。maxx保存当前的最大值 当所有的矩形都遍历一遍 取其中的最大值就是ans
要特别注意这个数据范围,因为y是顶着上限的,一加上h就更越过上限了
代码:
#include <map>
#include <cstdio>
#include <cstring>
#include <algorithm>
#define LL long long
using namespace std;
const int N=160005;
LL maxx[N],delta[N],ls[N];
map<int,int>mp;
struct hh{LL x,y1,y2,c;}seg[N];
int cmp(hh a,hh b){return a.x<b.x || (a.x==b.x && a.c>b.c);}
void updata(int now){maxx[now]=max(maxx[now<<1],maxx[now<<1|1]);}
void pushdown(int now)
{
if (delta[now])
{
delta[now<<1]+=delta[now];
delta[now<<1|1]+=delta[now];
maxx[now<<1]+=delta[now];
maxx[now<<1|1]+=delta[now];
delta[now]=0;
}
}
void change(int now,int l,int r,int lrange,int rrange,LL v)
{
if (lrange<=l && rrange>=r) {delta[now]+=(LL)v; maxx[now]+=(LL)v; return;}
int mid=(l+r)>>1;
pushdown(now);
if (lrange<=mid) change(now<<1,l,mid,lrange,rrange,v);
if (rrange>mid) change(now<<1|1,mid+1,r,lrange,rrange,v);
updata(now);
}
int main()
{
// freopen("stars.in","r",stdin);
// freopen("stars.out","w",stdout);
int n,w,h;
while (scanf("%d%d%d",&n,&w,&h)!=EOF)
{
int num=0;LL ans=0,x,y,c;
memset(maxx,0,sizeof(maxx));
memset(delta,0,sizeof(delta));
for (int i=1;i<=n;i++)
{
scanf("%lld%lld%lld",&x,&y,&c);
seg[++num].x=x; seg[num].y1=y; seg[num].y2=y+h-1; seg[num].c=c; ls[num]=y;
seg[++num].x=x+w-1; seg[num].y1=y; seg[num].y2=y+h-1; seg[num].c=-c; ls[num]=y+h-1;
}
sort(ls+1,ls+num+1);
int s=unique(ls+1,ls+num+1)-ls-1;
mp[ls[1]]=1;int now=1;
for (int i=2;i<=num;i++)
if (ls[i]==ls[i-1]) mp[ls[i]]=now;
else now++,mp[ls[i]]=now;
for (int i=1;i<=num;i++)
seg[i].y1=mp[seg[i].y1],seg[i].y2=mp[seg[i].y2];
sort(seg+1,seg+num+1,cmp);
for (int i=1;i<=num;i++)
{
change(1,1,now,seg[i].y1,seg[i].y2,seg[i].c);
ans=max(ans,maxx[1]);
}
printf("%lld\n",ans);
}
}