POJ P2482 Stars in Your Window

本文介绍了一种解决二维区间更新与查询问题的方法。通过将星星的坐标进行排序和离散化处理,利用线段树进行区间更新,最终找到最大值。代码实现了读取输入、建立线段树、执行区间更新操作并输出答案。

目录:


题目:

传送门


分析:

x x 从小到大排序,y值离散化,投影到 y y 轴上,那么对于每个星星的纵坐标,yy+h1就是每个星星可以影响到的矩形 然后 xx+w x , x + w 就是一个进入事件和一个出去事件,其所带的值互为相反数
t1.dat t 1 . d a t 保存当前的最大值 当所有的矩形都遍历一遍,然后 ans=max{t1.dat} a n s = m a x { t 1 . d a t }


代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>  
#include<cstdlib>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<list>
#include<ctime>
#include<iomanip>
#include<string>
#include<bitset>
#define LL long long
#define h happy
using namespace std;
inline LL read() {
    LL d=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
    return d*f;
}
struct node{
    LL x,y1,y2,f;
}e[20001];
struct segment_tree{
    LL l,r;
    LL dat,lazy;
}t[80001];
LL y[20001];
bool cmp(node x,node y)
{
    return x.x<y.x;
}
void build(LL p,LL l,LL r)
{
    t[p].l=l;t[p].r=r;
    t[p].dat=t[p].lazy=0;
    if(l==r) return;
    LL mid=(l+r)>>1;
    build(p*2,l,mid);
    build(p*2+1,mid+1,r);
    return;
}
void spread(LL p)
{
    t[p*2].dat+=t[p].lazy;
    t[p*2+1].dat+=t[p].lazy;
    t[p*2].lazy+=t[p].lazy;
    t[p*2+1].lazy+=t[p].lazy;
    t[p].lazy=0;
    return;
}
void change(LL p,LL l,LL r,LL w)
{
    if(y[t[p].l]==l&&y[t[p].r]==r) 
    {
        t[p].dat+=w;t[p].lazy+=w;
        return;
    }
    spread(p);
    LL mid=(t[p].l+t[p].r)>>1;
    if(r<=y[mid]) change(p*2,l,r,w);
    else if(l>y[mid]) change(p*2+1,l,r,w);
    else
    {
        change(p*2,l,y[mid],w);
        change(p*2+1,y[mid+1],r,w);
    }
    t[p].dat=max(t[p*2].dat,t[p*2+1].dat);
    return;
}
int main()
{
    LL n,w,h;
    while(scanf("%lld%lld%lld",&n,&w,&h)==3)
    {
        LL x,y1,c,cnt=0;
        for(LL i=1;i<=n;i++) 
        {
            x=read();y1=read();c=read();
            e[++cnt]=(node){x,y1,y1+h-1,c};
            y[cnt]=y1;
            e[++cnt]=(node){x+w,y1,y1+h-1,-c};
            y[cnt]=y1+h-1;
        }
        sort(y+1,y+1+cnt);
        sort(e+1,e+1+cnt,cmp);
        LL len=unique(y+1,y+cnt+1)-y-1;
        build(1,1,len);
        LL ans=0;
        for(LL i=1;i<=cnt;i++)
        {
            change(1,e[i].y1,e[i].y2,e[i].f);
            ans=max(ans,t[1].dat);
        }
        printf("%lld\n",ans);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值