题目链接:Stars in Your Window
题意:你有一个
W∗H
大小的矩形,每一颗星星有一个亮度属性,给出
n
颗星星的坐标,问能看到星星的亮度和最大为多少(恰好在边上的不算)
题解:经典的线段树+扫描线问题。先不考虑边界,如果我们把每一颗星星作为这个矩形的中心,那么当矩形中心位于这个矩形中的任意一点的时候,这颗星星是在矩形内的。那么当矩形中心被多个矩形覆盖的时候,这个矩形就包括了这些星星,所以这个问题就被转化成了线段树+扫描线:我们对于
#include <stdio.h>
#include <map>
#include <algorithm>
#include <iostream>
using namespace std;
const int N = 20005;
struct Node{
int l,r,v,tg;
}a[N<<2];
inline void PushUp(int i){
a[i].v=max(a[i<<1].v,a[i<<1|1].v);
}
void Build(int i,int l,int r){
a[i].l=l;
a[i].r=r;
a[i].tg=a[i].v=0;
if(l==r)
return ;
int mid=l+r>>1;
Build(i<<1,l,mid);
Build(i<<1|1,mid+1,r);
}
inline void PushDown(int i){
if(a[i].tg){
a[i<<1].tg+=a[i].tg;
a[i<<1].v+=a[i].tg;
a[i<<1|1].tg+=a[i].tg;
a[i<<1|1].v+=a[i].tg;
a[i].tg=0;
}
}
struct Line{
long long x,y,h;
int d;
}l[N<<1];
void Add(int i,int l,int r,int d){
if(l<=a[i].l&&a[i].r<=r){
a[i].v+=d;
a[i].tg+=d;
return ;
}
PushDown(i);
if(l<=a[i<<1].r)
Add(i<<1,l,r,d);
if(a[i<<1|1].l<=r)
Add(i<<1|1,l,r,d);
PushUp(i);
}
inline bool cmp(const Line& q,const Line& w){
if(q.h==w.h)
return q.d>w.d;
return q.h<w.h;
}
long long p[N<<1];
map<long long,int> Mp;
int main(){
int n;
long long w,h;
while(scanf("%d %lld %lld",&n,&w,&h)==3){
w*=2;
h*=2;
int cnt=0,c;
long long x,y;
for(int i=1;i<=n;i++){
scanf("%lld %lld %d",&x,&y,&c);
x*=2;
y*=2;
l[cnt].x=x-w/2+1;
l[cnt].y=x+w/2-1;
l[cnt].h=y-h/2+1;
l[cnt].d=c;
p[cnt++]=x-w/2+1;
l[cnt].x=x-w/2+1;
l[cnt].y=x+w/2-1;
l[cnt].h=y+h/2-1;
l[cnt].d=-c;
p[cnt++]=x+w/2-1;
}
sort(l,l+cnt,cmp);
sort(p,p+cnt);
int len=unique(p,p+cnt)-p;
Mp.clear();
for(int i=0;i<len;i++)
Mp[p[i]]=i+1;
int ans=0;
Build(1,1,len);
for(int i=0;i<cnt;i++){
Add(1,Mp[l[i].x],Mp[l[i].y],l[i].d);
ans=max(ans,a[1].v);
}
printf("%d\n",ans);
}
return 0;
}