POJ 2482 Stars in Your Window

题目链接Stars in Your Window
题意:你有一个 WH 大小的矩形,每一颗星星有一个亮度属性,给出 n 颗星星的坐标,问能看到星星的亮度和最大为多少(恰好在边上的不算)
题解:经典的线段树+扫描线问题。先不考虑边界,如果我们把每一颗星星作为这个矩形的中心,那么当矩形中心位于这个矩形中的任意一点的时候,这颗星星是在矩形内的。那么当矩形中心被多个矩形覆盖的时候,这个矩形就包括了这些星星,所以这个问题就被转化成了线段树+扫描线:我们对于x轴方向的线段建立线段树然后向 y 方向遍历即可。边界问题可通过将坐标2解决,由于坐标范围较大,为了防止MLE,我们建立线段树之前先利用map离散化。

#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;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值