zoukankan      html  css  js  c++  java
  • P1502 窗口的星星(扫描线入门第一题)

    题目链接:https://www.luogu.org/problem/P1502

    P1502 窗口的星星

    提交2.78k
    通过682
    时间限制1.00s
    内存限制125.00MB
    题目提供者cyrcyr
    历史分数100
     提交记录  查看题解

    标签

     查看算法标签

    相关讨论

    进入讨论版
     查看讨论

    推荐题目

     查看推荐
     展开

    题目背景

    小卡买到了一套新房子,他十分的高兴,在房间里转来转去。

    题目描述

    晚上,小卡从阳台望出去,“哇~~~~好多星星啊”,但他还没给其他房间设一个窗户,天真的小卡总是希望能够在晚上能看到最多最亮的星星,但是窗子的大小是固定的,边也必须和地面平行。这时小卡使用了超能力(透视术)知道了墙后面每个星星的位置和亮度,但是小卡发动超能力后就很疲劳,只好拜托你告诉他最多能够有总和多亮的星星能出现在窗口上。

    输入格式

    本题有多组数据,第一行为T 表示有T组数据T<=10

    对于每组数据

    第一行3个整数n,W,H,(n<=10000,1<=W,H<=1000000)表示有n颗星星,窗口宽为W,高为H。

    接下来n行,每行三个整数xi,yi,li 表示星星的坐标在(xi,yi),亮度为li。(0<=xi,yi<2^31)

    输出格式

    T个整数,表示每组数据中窗口星星亮度总和的最大值。

    输入输出样例

    输入 #1
    2
    3 5 4
    1 2 3
    2 3 2
    6 3 1
    3 5 4
    1 2 3
    2 3 2
    5 3 1
    
    输出 #1
    5
    6
    

    说明/提示

    小卡买的窗户框是金属做的,所以在边框上的不算在内。

    思路:就是扫描线的板子题,在这里记录一下自己理解的扫描线:

    线段树维护y轴区间,x轴暴力,这是扫描线的精髓。 相当于一条条线沿着x轴扫过去,看一下为什么这样能解决问题:

    把每一个星星作为左下角,在它的右上方划出一片窗口大小的区域,表示只要窗口的右上角落在这一片区域里就一定能覆盖到这颗星星。

    那么不同星星的重叠部分就代表能同时覆盖这几颗星星了。

    (下图中(这里是以星星为左下角,两种方式都行),只要窗口落在阴影部分,就能同时覆盖到三颗星星) 

    看代码:

     

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int maxn=4e4+5;
    typedef long long LL;
    LL ly[maxn<<2];//存所有的y 离散化
    LL lazy[maxn<<2],ma[maxn<<2];//线段树延迟标记  存最大值
    int len;//
    struct Node
    {
        LL x,y,v,f,l,r;//x y v为坐标 f标记是起始边还是结束边  l r代表y轴区域
    }node[maxn<<2];//存下所有的边
    bool cmp(const Node a,const Node b)
    {
        if(a.x==b.x) return a.f<b.f;//相等的话 先结束 再开始
        return a.x<b.x;
    }
    void Push_down(LL rt)
    {
        ma[rt<<1]+=lazy[rt];
        ma[rt<<1|1]+=lazy[rt];
        lazy[rt<<1]+=lazy[rt];
        lazy[rt<<1|1]+=lazy[rt];
        lazy[rt]=0;
    }
    void Update(LL l,LL r,LL rt,LL L,LL R,LL v)
    {
    //    cout<<"l:"<<l<<" r:"<<r<<" L:"<<L<<" R:"<<R<<" v:"<<v<<endl;
        if(L<=l&&r<=R)
        {
            ma[rt]+=v;lazy[rt]+=v;return ;
        }
        LL mid=(l+r)>>1;
        if(lazy[rt]) Push_down(rt);
        if(L<=mid) Update(l,mid,rt<<1,L,R,v);
        if(R>mid) Update(mid+1,r,rt<<1|1,L,R,v);
        ma[rt]=max(ma[rt<<1],ma[rt<<1|1]);
    }
    LL getid(LL x)
    {
        return lower_bound(ly+1,ly+len+1,x)-(ly);
    }
    int main()
    {
        int T;scanf("%d",&T);
        while(T--)
        {
            memset(lazy,0,sizeof(lazy));memset(ma,0,sizeof(ma));
            LL N,W,H;scanf("%lld%lld%lld",&N,&W,&H);
            int p=0,p1=0;
            for(int i=1;i<=N;i++)
            {
                LL x,y,v;scanf("%lld%lld%lld",&x,&y,&v);
                ly[++p1]=y;
                node[++p].x=x;node[p].y=y;node[p].v=v;node[p].f=1;//起始边
                node[p].l=y;node[p].r=y+H-1;//这里的边界一定要注意 很有可能会错
                x=x+W;y=y+H-1;
                ly[++p1]=y;
                node[++p].x=x;node[p].y=y;node[p].v=v;node[p].f=-1;//结束边
                node[p].l=node[p-1].l;node[p].r=node[p-1].r;
            }
            sort(ly+1,ly+p1+1);
            len=unique(ly+1,ly+p1+1)-(ly+1);
            sort(node+1,node+p+1,cmp);
    //        for(int i=1;i<=p;i++) cout<<node[i].x<<" "<<node[i].y<<" "<<node[i].v<<endl;
            LL ans=0;
            for(int i=1;i<=p;i++)// 遍历所有的边
            {
                LL l=node[i].l;
                LL r=node[i].r;
                l=getid(l);r=getid(r);
    //            cout<<"i="<<i<<" f="<<node[i].f<<" val="<<node[i].v<<endl;
                Update(1,len,1,l,r,node[i].f*node[i].v);
                ans=max(ans,ma[1]);
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
    /**
    2
    3 5 4
    1 2 3
    2 3 2
    6 3 1
    */
    当初的梦想实现了吗,事到如今只好放弃吗~
  • 相关阅读:
    基于mybatis的crud demo
    事务的隔离级别
    spring中ioc的实现
    spring中xml配置文件
    spring中AOP的实现
    mybatis框架
    基于Mapreduce的并行Dijkstra算法执行过程分析
    算法技巧:位运算 逻辑运算
    day04_09 while循环03
    day04_08 while循环02
  • 原文地址:https://www.cnblogs.com/caijiaming/p/11504308.html
Copyright © 2011-2022 走看看