• 窗口的星星


    题目描述

    平面上有 \(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); 
        } 
    }
    
  • 相关阅读:
    JavaWeb网站技术架构
    fullcalendar插件日程管理
    PuTTY/终端使用复制、粘贴
    JAVA PERSISTENCE API (JPA)
    mysql查询当天所有数据sql语句
    Sign http
    js在新页面中返回到上一页浏览的历史位置
    Android使用Activity用作弹出式对话框
    android listview局部刷新和模拟应用下载
    如何获取drawable目录下的图片绝对路径
  • 原文地址:https://www.cnblogs.com/wwlwQWQ/p/13650140.html
Copyright © 2020-2023  润新知