窗内的星星

题目链接

题意:已知每个星星的坐标和亮度,求用一个宽w,高h的矩形能圈住的星星的亮度总和最大是多少。

思路:我们把每个星星置为w,h矩形的左下角,这样围才是最多的情况。然后将每个这样的搞出来并把其矩形赋权为其亮度,可以发现当两个矩形重合的地方就可以用亮度加起来

表示,因为在那个地方做宽w高h的矩形两个星星都圈的起来。所以问题就又变成了求坐标上重叠区域的最大权值和。

根据扫描线,我们先对x坐标排序,设星星(x,y,c)c为亮度,保存两个四元组(x,y,y+h-1,c)和(x+w,y,y+h-1,-c)。维护对于当前x,y坐标整点上权值和的最大值。区间修改+c,-c就相当于

只在x到x+c的区间内亮度+c。

 

#include<cstring>
#include<algorithm>
#include<vector>
#include<map>
#include<queue>
#include<cstdio>
#include<cmath>
#define int long long
#define lowbit(x) x&(-x)
using namespace std;
const int N=2e4+10;
struct node{
    int x,y1,y2;
    int c;
    node() {}
    node(int x, int y1,int y2,int c){
        this->x = x; this->c = c;
        this->y1 = y1; this->y2 = y2;
    }
    bool operator <(const node &t)const {
        return x<t.x;
    }
}a[N];
int n,w,h,y[N];
struct Tree
{
    int l,r;
    int len,lazy;
}t[N<<2];
void pushup(int p)
{
    t[p].len=max(t[p<<1].len,t[p<<1|1].len)+t[p].lazy;
}
void build(int p,int l,int r)
{
    t[p].l=y[l];
    t[p].r=y[r];
    t[p].lazy=0;
    t[p].len=0;
    if(r-l==1)
    {
        return;
    }
    int mid=(l+r)>>1;
    build(p<<1,l,mid);
    build(p<<1|1,mid,r);
}
void update(int l,int r,int k,int p)
{
    if(t[p].l>=l&&t[p].r<=r)
    {
        t[p].lazy+=k;
        t[p].len+=k;
        return;
    }
    if(l<t[p<<1].r)
        update(l,min(r,t[p<<1].r),k,p<<1);
    if(r>t[p<<1|1].l)
        update(max(l,t[p<<1|1].l),r,k,p<<1|1);
    pushup(p);
}
signed main()
{
    while(~scanf("%lld%lld%lld",&n,&w,&h))
    {
        int cnt=0,num=1;
        for(int i=1;i<=n;i++)
        {
            int xx,yy,k;
            scanf("%lld%lld%lld",&xx,&yy,&k);
            a[cnt++]=node(xx,yy,yy+h,k);
            a[cnt++]=node(xx+w,yy,yy+h,-k);
            y[num++]=yy;
            y[num++]=yy+h;
        }
        sort(y+1,y+num);
        int ans=0;
        num=unique(y+1,y+num)-(y+1);
        sort(a,a+cnt);
        build(1,1,num);
        for(int i=0; i<cnt; i++)
        {
            update(a[i].y1,a[i].y2,a[i].c,1);
            if(a[i].c>0)
                ans=max(ans,t[1].len);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

posted @ 2019-08-17 16:01  Ldler  Views(198)  Comments(0Edit  收藏  举报