「POJ2482」Stars in Your Window 题解 (线段树,扫描线)
题目简介
好唯美抒情的文字 (ノへ ̄、)
Google 翻译:
流年不会模糊我对你的记忆。我第一次见到你真的可以四年了吗?我还清楚地记得,四年前,在美丽的珠海校区,从看到你微笑的那一刻起,当你走出教室,转过头来,柔和的晚霞照在你红润的脸颊上,我知道,我知道我已经对你醉了。然后,经过几个月的观察和窥探,你的风度和智慧,你的生活态度,你对未来的憧憬,都深深地印在了我的记忆中。你是我一直梦想与她共度余生的迷人阳光女孩。唉,实际上你远远超出了我最疯狂的梦想,我不知道如何弥合你我之间的鸿沟。所以我什么也没有计划,只是等待,等待一个合适的机会。
这些天,与朋友、室友、同学陆续离别,我还是不敢相信,挥了挥手,这些熟悉的面孔很快就会从我们的生活中消失,成为回忆。我明天要从学校搬出去。而你正打算远走高飞,追寻未来,实现梦想。如果没有缘分和运气,也许我们就不会再见了。所以今晚,我在你的宿舍楼里闲逛,希望能在那里遇见你。但矛盾的是,你的出现肯定让我心跳加速,我笨拙的舌头可能吐不出一个字来。我记不清有多少次路过你在珠海和广州的宿舍楼,每一次都渴望看到你出现在阳台上,看到你投在窗户上的身影。我不记得有多少次这个想法出现在我的脑海中:叫她出去吃晚饭或至少谈话。但每一次,想到你的优秀和我的平凡,胆怯胜过勇气,我都默默地离开了。
毕业,意味着大学生活的结束,这些光辉浪漫的岁月的结束。你可爱的笑容,是我努力工作的原动力,这份单恋,都将铭刻在心底深处。毕业,也意味着新生活的开始,在走向光明的道路上留下足迹。我真的希望你在国外每天都开心,一切顺利。同时,我会努力摆脱幼稚,变得更加成熟。在现实中追求自己的爱情和幸福将是我从未放弃的理想。
再见了,我的公主!
如果有一天,某地,有机会相聚,哪怕是白发苍苍的男人和女人,那个时候,我希望我们能成为好朋友,骄傲地分享这段记忆,重燃青春快乐的情感。如果这个机会永远不会到来,我希望我是天上的星星,在你窗外闪烁,祝福远方的你,像朋友一样,陪你每晚,分享甜蜜的梦,或一起度过噩梦。
问题来了:假设天空是平面。所有的星星都位于其上,位置为 (x, y)。每颗星星都有1到100的等级,代表它的亮度,100最亮,1最弱。窗口是一个矩形,其边平行于 x 轴或 y 轴。你的任务是告诉我应该把窗户放在哪里,以便最大化窗户内星星的亮度总和。请注意,窗口边缘的星星不计算在内。窗口可以平移,但不允许旋转。
言归正传:分析
已知矩形的大小形状是固定的,我们可以考虑选择一个顶点来确定矩形位置,这里默认为右上角顶点,那么我们就可以作出以每颗星星的位置为左下角的同等大小的矩形。
如果矩形右上角在星星矩形范围内(根据题意,不包含窗边的星星),那么星星就一定会被网住。
基本实现:
- 输入数据,构建扫描线模型;
- 去重排序;
- 依照扫描线建线段树;
- 依次将每颗星星加入线段树中,打擂台求答案。
AC 代码
#include<bits/stdc++.h>
using namespace std;
const int maxn=10005;
int read(){
int x=0,f=1;
char ch=getchar();
while(ch<'0'||ch>'9'){
if(ch=='-')f=-1;
ch=getchar();
}
while(ch>='0'&&ch<='9'){
x=(x<<1)+(x<<3)+(ch^48);
ch=getchar();
}
return x*f;
}
struct star{
int x,y,z;
int c;
void input(){
x=read();y=read();c=read();
}
void output(){
printf(" x = %-2d, y = %-2d, z = %-2d, c = %-2d\n",x,y,z,c);
}
friend bool operator<(star fir,star sec){
return fir.x<sec.x||(fir.x==sec.x&&fir.c<sec.c);
}
}a[maxn<<1];
int b[maxn<<1];
int n,w,h;
struct segment_tree{
int l,r;
int val;
int lazy;
}tr[maxn<<4];
//#define put printf(" [%d, %d] %d, %d\n",tr[k].l,tr[k].r,tr[k].val,tr[k].lazy)
void build(int k,int l,int r){
tr[k].l=l;
tr[k].r=r;
tr[k].val=tr[k].lazy=0;
if(l==r)return ;
int mid=(l+r)>>1;
build(k<<1,l,mid);
build(k<<1|1,mid+1,r);
}
void push_down(int k){
tr[k<<1].lazy+=tr[k].lazy;
tr[k<<1].val+=tr[k].lazy;
tr[k<<1|1].lazy+=tr[k].lazy;
tr[k<<1|1].val+=tr[k].lazy;
tr[k].lazy=0;
}
void push_up(int k){
tr[k].val=max(tr[k<<1].val,tr[k<<1|1].val);
}
void change(int k,int l,int r,int c){
if(l<=tr[k].l&&tr[k].r<=r){
tr[k].val+=c;
tr[k].lazy+=c;
// put;
return ;
}
if(tr[k].lazy)push_down(k);
int mid=(tr[k].l+tr[k].r)>>1;
if(l<=mid)change(k<<1,l,r,c);
if(r>mid)change(k<<1|1,l,r,c);
push_up(k);
// put;
}
int main(){
while(scanf("%d%d%d",&n,&w,&h)!=EOF){
for(int i=1;i<=n;i++){
int k=i<<1;
a[k-1].input();
a[k].x=a[k-1].x+w;
b[k-1]=a[k].y=a[k-1].y;
b[k]=a[k].z=a[k-1].z=a[k-1].y+h-1;
a[k].c=-a[k-1].c;
// a[k-1].output();
// a[k].output();
// printf(" b[%d] = %d\n b[%d] = %d\n",k-1,b[k-1],k,b[k]);
}
n<<=1;
sort(b+1,b+1+n);
int m=unique(b+1,b+1+n)-(b+1);
// printf(" m = %d\n",m);
for(int i=1;i<=n;i++){
a[i].y=lower_bound(b+1,b+1+m,a[i].y)-b;
a[i].z=lower_bound(b+1,b+1+m,a[i].z)-b;
// printf(" [%d, %d)\n",a[i].y,a[i].z);
}
sort(a+1,a+1+n);
// for(int i=1;i<=n;i++)a[i].output();
build(1,1,m);
int ans=0;
for(int i=1;i<=n;i++){
change(1,a[i].y,a[i].z,a[i].c);
ans=max(ans,tr[1].val);
}
printf("%d\n",ans);
}
return 0;
}