窗口的星星
Link
题目描述
平面上有 \(n\) 个点,现用一个 \(w\times h\) 大小的矩形边框来框这些点(边界上的点不算),问最多能框柱多少点。
解法
直接求范围 \(w\times h\) 的点的个数不好维护。考虑反过来,对于一个确定的点,哪些矩形边框可以把它框柱。但这样还是不能维护,再次转换,这次只考虑矩形左下角的范围,我们发现范围就是以那个确定点为左下角的 \(w\times h\) 的矩形。那么所有点对应的这些矩形共同构成了一个完整的图形,所求答案即为这些矩形重叠次数的最大值。可以直接用扫描线维护。
边界处理:对于边界上的点不能算,那么考虑把矩形四边的大小都减少 \(0.5\) ,之后又进一步转换为整数范围 \((x,y)\) 到 \((x+w-1,y+h-1)\)。
#include<stdio.h>
#include<string.h>
#include<algorithm>
using namespace std;
#define N 40007
#define int long long
#define ll long long
#define lid id<<1
#define rid id<<1|1
inline ll read(){
ll x=0,flag=1;char c=getchar();
while(c<'0'||c>'9'){if(c=='-') flag=0;c=getchar();}
while(c>='0'&&c<='9'){x=(x<<1LL)+(x<<3LL)+c-48LL;c=getchar();}
return flag? x:-x;
}
struct E{
int x,l,r;
ll val;
}e[N];
int T,W,H,n;
ll s[N<<2],tag[N<<2],t[N];
bool Cmp(E a,E b){
if(a.x!=b.x) return a.x<b.x;
return a.val>b.val;
}
ll val;
int l,r;
inline ll max(ll x,ll y){return x>y? x:y;}
inline void update(int id){s[id]=max(s[lid],s[rid]);}
inline void pushup(int id,ll v){tag[id]+=v;s[id]+=v;}
inline void pushdown(int id){
pushup(lid,tag[id]);
pushup(rid,tag[id]);
tag[id]=0;
}
void modify(int id,int lf,int rf){
if(l<=lf&&rf<=r)
pushup(id,val);
else{
int mid=(lf+rf)>>1;
if(tag[id]) pushdown(id);
if(l<=mid) modify(lid,lf,mid);
if(mid<r) modify(rid,mid+1,rf);
update(id);
}
}
void print(int *a,int r){
for(int i=1;i<=r;i++) printf("%d ",t[i]);
putchar('\n');
}
void build(int id,int lf,int rf){
s[id]=tag[id]=0;
if(lf==rf) return ;
int mid=(lf+rf)>>1;
build(lid,lf,mid);
build(rid,mid+1,rf);
}
signed main(){
// freopen("data.in","r",stdin);
// freopen("mine.out","w",stdout);
T=read();
while(T--){
n=read(),W=read(),H=read();
for(int i=1;i<=n;i++){
int x,y; ll l;
x=read(),y=read(),l=read();
e[(i<<1)-1]=(E){x,y,y+H-1,l};
e[(i<<1)]=(E){x+W-1,y,y+H-1,-l};
t[(i<<1)-1]=y;
t[(i<<1)]=y+H-1;
}
n<<=1;
sort(t+1,t+1+n);
int sz=unique(t+1,t+1+n)-(t+1);
build(1,1,sz);
sort(e+1,e+1+n,Cmp);
ll ans=0;
//print(t,sz);
for(int i=1;i<=n;i++){
l=lower_bound(t+1,t+1+sz,e[i].l)-t;
r=lower_bound(t+1,t+1+sz,e[i].r)-t;
val=e[i].val;
modify(1,1,sz);
ans=max(ans,s[1]);
}
printf("%lld\n",ans);
}
}