窗口的星星

题目描述

平面上有 \(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); 
    } 
}
posted @ 2020-10-04 19:32  Kreap  阅读(70)  评论(0编辑  收藏  举报