首页 > 其他 > 详细

【Luogu P1502】窗口的星星

时间:2019-11-02 18:39:22      阅读:102      评论:0      收藏:0      [点我收藏+]

Luogu P1502

题意很好理解,就是问给出的矩形套住的最大和。

但是做起来却十分麻烦。

技术分享图片
技术分享图片

——来自疯狂爆10分的愤怒

一个比较高效的思路是——把每一个星星作为左下角向右上方拓展形成一个矩形,
拓展的规则为只要窗口的右上角在这个矩形之内,就可以覆盖到这个星星。然后用线段树维护一条扫描线从左往右扫过去,寻找单点的最大值。

值得注意的是题面提出了窗框上的星星不计入答案,这样一搞整道题就变得相当恶心了

一个比较好理解且比较方便的做法就是以星星的横纵坐标+0.5作为矩形的左下角。

那么这样就能保证这个矩形符合拓展的规则了。

另外,由于星星的坐标很大,可以使用离散化缩小范围

code time:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#define lson root<<1
#define rson root<<1|1
#define ll long long
using namespace std;
struct data
{
    double l,r,x;
    ll flag;
}line[80005];
bool cmp(data a,data b)
{
    if (a.x==b.x) return a.flag<b.flag;
    return a.x<b.x;
    //重点之一,注意权值小的排在前面,因为在矩形的右边界上,这颗星星已经对答案没有贡献了
}
ll tag[80005],tree[80005],n,w,h,x,y,l,cnt,ans,T;
double pnt[80005];
void push_down(ll root,ll l,ll r)
{
    tag[lson]+=tag[root];
    tag[rson]+=tag[root];
    tree[lson]+=tag[root];
    tree[rson]+=tag[root];
    tag[root]=0;    
}*/
void update(ll root,ll l,ll r,double L,double R,ll flag)
{
    if (L<=pnt[l]&&pnt[r]<=R)
    {
        tag[root]+=flag;
        tree[root]+=flag;
        return ;
    }
    if (l+1==r) return ;
    if (R<=pnt[l]||L>=pnt[r]) return ;
    push_down(root,l,r);
    //事实上不需要pd操作也能过。
    ll mid=(l+r)>>1;
    if (L<pnt[mid]) update(lson,l,mid,L,R,flag);
    if (R>pnt[mid]) update(rson,mid,r,L,R,flag);
    //注意离散化后mid仅为下标,而不是坐标。
    tree[root]=max(tree[lson],tree[rson])+tag[root];
}
int main()
{
    scanf("%d",&T);
    for (int q=1;q<=T;q++)
    {
        cnt=0;
        ans=0;
        memset(line,0,sizeof(line));
        memset(pnt,0,sizeof(pnt));
        memset(tree,0,sizeof(tree));
        memset(tag,0,sizeof(tag));
        //记得要初始化
        scanf("%d%d%d",&n,&w,&h);
        for (int i=1;i<=n;i++)
        {
            scanf("%d%d%d",&x,&y,&l);
            line[++cnt].x=x+0.5;line[cnt].l=y+0.5;line[cnt].r=y+h;line[cnt].flag=l;pnt[cnt]=y+h;
            line[++cnt].x=x+w;line[cnt].l=y+0.5;line[cnt].r=y+h;line[cnt].flag=-l;pnt[cnt]=y+0.5;
            //重点之一,对边界的处理
        }
        sort(line+1,line+1+cnt,cmp);
        sort(pnt+1,pnt+1+cnt);
        ll til=unique(pnt+1,pnt+1+cnt)-pnt-1;
        for (int i=1;i<=cnt;i++)
        {
            update(1,1ll,til,line[i].l,line[i].r,line[i].flag);
            ans=max(ans,tree[1]);
        }
        printf("%lld\n",ans);
    }
    return 0;
}

【Luogu P1502】窗口的星星

原文:https://www.cnblogs.com/notscience/p/11783401.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!