poj2482/洛谷1502 线段树+扫描线

题目大意

(洛谷上的翻译)
飞逝的的时光不会模糊我对你的记忆。难以相信,从我第一次见到你以来已有3年光阴。我仍然还真切地记得,3年前,在美丽的集美中学,从我看到你微笑着走出教室,你将头向后仰,柔和的晚霞照耀着你玫瑰色的脸颊。我明白,我已经沉醉于你了。之后,经过几个月的观察和窥探,你的优雅与智慧,你对待生活的态度和你对未来的愿望深切地在我心中留下了印象。你是迷人的阳光女孩,我总是梦想着与你分享余生。唉,实际上你远远超过了我最疯狂的梦想。我不知道如何桥起我与你之间的鸿沟。所以我没有任何计划,仅仅只是等待,等待一个适当的机会到来。直到现在,毕业的到来,我意识到我是个傻瓜,我应该创造机会并且抓住它而不只是等待。

这些日子里,我和我的朋友、室友、同学一个接一个地分开。我仍无法相信,在挥手之后,这些熟悉的面孔很快就会从我们的生活中消失,仅仅留下回忆。我明天就将离开学校。你已经计划远走高飞,追求你的未来,实现你的梦想。如果没有命运,也许我们不会再次相遇。所以今晚,我正在你的宿舍楼下徘徊,希望能偶然遇见你。但矛盾的是,你的美貌一定会使我心跳加速,我笨拙的舌头也许无法吐出一个字。我不记得我曾多少次经过你的宿舍楼,每次都希望看到你出现在阳台上或是窗台上。我不记得这个想法曾多少次在我的脑海中涌出:打电话叫她一起吃晚饭或是聊聊天。但每次,考虑到你的优秀和我的平凡,胆怯的优势超越勇气驱使我静静地离开。

毕业,意味着中学生活的终结。这些光荣与浪漫的时代结束。你可爱的微笑是我原来努力学习的动力,这单相思的爱情会被密封,作为一个我心灵深处的记忆。毕业,也意味着新生活的开始,一个到达光明未来的足迹。我真希望你在国外天天开心,一切顺利。同时,我将努力从幼稚中走出来,变得更加成熟。我的理想将是在现实中追求我的爱与幸福,我永远不会放弃。

再见了,我的公主!

如果有一天,在某个天涯海角,我们有机会相聚,即使我们已经成为白发苍苍的男人和女人,在那个时候,我希望我们可以成为好朋友来自豪地分享这个记忆,重温年轻快乐的激情。如果这个机会永远没有到来,我希望我是天空中的星星,在你的窗外闪烁。远远地保佑着你,就像一个朋友,每天晚上陪伴在你左右,一同分享甜美的梦亦或是一同经历可怕的梦。

现在问题来了:天空可以理解为一条数轴,在这条数轴上分布着许多颗星星,对于每颗星星都有它的位置Xi和自身的亮度Bi。而窗户所能看到的范围是一个给出的参数W,我们看到的星星也包括窗户边缘的星星。现在,要你求出调整窗户位置后能看到星星的亮度之和最大值。

解题思路

你将你w*h的明窗在天幕间慢慢的移动,我知道,承载我心愿的某一颗星星,它在什么时候到达你的窗棂前,又什么时候离去。离去总是比到来,更加急促,总是使我无法做好准备。
(翻译:将每一颗星星看作两条扫描线,一条表示窗户只看长度的情况下,右边边框移到什么地方会使这颗星星出现,什么地方会消失。按照x坐标排序,为了避免计算已经消失的星星,对于x坐标相同的星星,表示消失的扫描线要排序在前面)
我可不可以用右侧捎来的书信,来寄托我的心绪?每一颗微小的星啊,你们的笑颜汇聚一堂的时候,你便再也不用东奔西走,四处搜罗。你只要轻轻地抬头,望啊,那最亮最亮的光芒,你看见了吗?
(翻译:用线段树维护y坐标上的星星,求一个序列里面一个高度为h的区间总和最大值的方法:区间更新,对于每一颗星星,将它的贡献(亮度)加到所有高度为h,可以看见它的区间的右端点上,然后答案就是单点最大值了)
可惜我笨拙的嘴舌无法将这些说尽千分之一,但是你真正体悟的时候,一定会懂的吧。
(翻译:我语死早,不懂请看代码)

代码

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<climits>
using namespace std;
#define LL long long
const int N=10005;
int T,n,cn,ynum;
LL w,h,ans;
LL y[N<<1],mx[N<<3],laz[N<<3];
struct line{LL x,y1,y2,c;}s[N<<1];
void add(int l,int r,int st,int t,int i,LL num){
    if(l<=st&&t<=r){laz[i]+=num,mx[i]+=num;return;}
    int mid=(st+t)>>1,ls=(i<<1),rs=(i<<1)|1;
    if(laz[i]){
        laz[ls]+=laz[i],laz[rs]+=laz[i];
        mx[ls]+=laz[i],mx[rs]+=laz[i];
        laz[i]=0;
    }
    if(l<=mid)add(l,r,st,mid,i<<1,num);
    if(mid+1<=r)add(l,r,mid+1,t,(i<<1)|1,num);
    mx[i]=max(mx[i<<1],mx[(i<<1)|1]);
}
void work(){
    int i;ans=0;
    memset(mx,0,sizeof(mx));memset(laz,0,sizeof(laz));
    for(i=1;i<=cn;++i){
        s[i].y1=lower_bound(y+1,y+1+ynum,s[i].y1)-y;
        s[i].y2=lower_bound(y+1,y+1+ynum,s[i].y2)-y;
        add(s[i].y1,s[i].y2,1,ynum,1,s[i].c);
        ans=max(ans,mx[1]);
    }
    printf("%lld\n",ans);
}
bool cmp(line xx,line yy){
    if(xx.x==yy.x)return xx.c<yy.c;//注意先处理负的再处理正的,否则本应该减掉的星星可能在没有
    return xx.x<yy.x;
}
int main(){
    int i;LL kc,kx,ky;
    while(~scanf("%d%lld%lld",&n,&w,&h)){
        cn=0;
        for(i=1;i<=n;++i){
            scanf("%lld%lld%lld",&kx,&ky,&kc);
            s[++cn].x=kx,s[cn].y1=ky,s[cn].y2=ky+h-1,s[cn].c=kc;
            s[++cn].x=kx+w,s[cn].y1=ky,s[cn].y2=ky+h-1,s[cn].c=-kc;
            y[i]=ky,y[n+i]=ky+h-1;
        }
        sort(s+1,s+1+cn,cmp);sort(y+1,y+1+n*2);
        ynum=1;for(i=2;i<=n*2;++i)if(y[i]!=y[ynum])y[++ynum]=y[i];
        work();
    }
    return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值