您的位置:首页 > 其它

poj 2482 Stars in Your Window(线段树,扫描线)

2014-05-05 12:22 357 查看
poj 2482 Stars in Your Window

题意,移动一个固定大小的矩形,使矩形中的星星亮度之和最大(边框上的不算),输出该值

这个题把可移动的矩形转换为扫描线的方式来做非常巧妙,以每颗星星(亮度为val)为左下角建立一个矩形(向Y轴映射),左竖边的值就为val,右竖边的值为-val,试想一下如果有两个矩形有重叠部分的话那么这两个矩形所代表的两颗星星必定能被一个矩形圈在一起,这样我们就能利用扫描线求出重叠部分的值。

离散化后进行扫描线操作,每个节点Lazy维护一个最大值maxval,这样每一次插入一条线在根节点就保存得有当前整棵树最大值,即当前矩形能圈住的最大值。

需要注意的:

因为边框上的星星不算在矩形内,所以排序的时候在x坐标相同的情况下,val值小的应在前面

我的写法中可能有中间结果超int,导致出现负数,然后一直RE啊RE(吐血)、、、本来可以1A的,一怒之下全改成long long、、、

#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
#include<iostream>
using namespace std;
#define ll long long
#define MAXN 200100
#define lch p<<1
#define rch p<<1|1
struct ele
{
ll x,yd,yu;
ll val;
bool operator < (const ele &a) const
{
if(x==a.x)
return val<a.val;
else return x<a.x;
}
}seg[MAXN*4];
struct node
{
ll l,r;
ll val;
ll maxval;
}t[MAXN*8];
ll max(ll a,ll b) {return a>b?a:b;}
void construct(ll l,ll r,ll p)
{
t[p].l=l,t[p].r=r;
t[p].val=t[p].maxval=0;
if(r-l<=1) return ;
ll m=(l+r)>>1;
construct(l,m,lch);
construct(m,r,rch);
}
void pushdown(ll p)
{
t[lch].val+=t[p].val;
t[rch].val+=t[p].val;
t[lch].maxval+=t[p].val;
t[rch].maxval+=t[p].val;
t[p].val=0;
}
void modify(ll l,ll r,ll val,ll p)
{
if(t[p].l==l&&t[p].r==r)
{
t[p].maxval+=val;
t[p].val+=val;
return ;
}

if(t[p].val) pushdown(p);

ll m=(t[p].l+t[p].r)>>1;
if(r<=m) modify(l,r,val,lch);
else if(l>=m) modify(l,r,val,rch);
else modify(l,m,val,lch),modify(m,r,val,rch);

t[p].maxval=max(t[lch].maxval,t[rch].maxval);
}
ll yy[MAXN*4];
map<ll,ll> rec;
int main()
{
//freopen("in.txt","r",stdin);
//freopen("out.txt","w",stdout);
ll i,n,w,h,x,y,val;
while(scanf("%lld%lld%lld",&n,&w,&h)!=EOF)
{
for(i=0;i<(n<<1);i+=2)
{
scanf("%lld%lld%lld",&x,&y,&val);
seg[i].x=x,seg[i].yd=y,seg[i].yu=y+h,seg[i].val=val;
seg[i+1].x=x+w,seg[i+1].yd=y,seg[i+1].yu=y+h,seg[i+1].val=-val;
yy[i]=y;
yy[i+1]=y+h;
}
sort(seg,seg+(n<<1));
sort(yy,yy+(n<<1));
ll up=(int)(unique(yy,yy+(n<<1))-yy);
rec.clear();
for(i=0;i<up;i++)
rec[yy[i]]=i;//printf("%d\n",yy[i]);
ll ans=0;
construct(0,up,1);
for(i=0;i<(n<<1);i++)
{
modify(rec[seg[i].yd],rec[seg[i].yu],seg[i].val,1);
ans=max(ans,t[1].maxval);
}
printf("%lld\n",ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  线段树 扫描线