poj2482 线段树扫描线

一开始没什么想法,看了点提示,居然是把每个点换成矩形。代码立即敲出来了,不过由于二分查找的时候形参没用LL,结果就悲剧了一天。幸好把代码打出来找到错误了,做完又去看了个离线算法。。。


ACcode:

在线:


#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define LL long long
using namespace std;

const int nsize=111111;

LL X[nsize<<1];
int sum[nsize<<3],cov[nsize<<3];

struct Line
{
    LL lx,rx,y;
    int f;
    Line(){}
    Line(LL a,LL b,LL c,int d) : lx(a),rx(b),y(c),f(d){}
    bool operator < (const Line &cmp) const {
        if(y==cmp.y)
            return f>cmp.f;
        return y<cmp.y;
    }
}line[nsize<<1];

int Max(int a1,int a2)
{
    return a1>a2?a1:a2;
}

int Fin(LL key,int k)
{
    int l=0,r=k;
    while (l<=r)
    {
        int m=(l+r)>>1;
        if (X[m]==key) return m;
        else if (X[m]>key) r=m-1;
        else l=m+1;
    }
    return -1;
}

void PushUp(int rt)
{
    sum[rt]=Max(sum[rt<<1],sum[rt<<1|1]);
}

void PushDown(int rt)
{
    if (cov[rt]!=0)
    {
        cov[rt<<1]+=cov[rt];
        sum[rt<<1]+=cov[rt];
        cov[rt<<1|1]+=cov[rt];
        sum[rt<<1|1]+=cov[rt];
        cov[rt]=0;
    }
}

void update(int rt,int l,int r,int L,int R,int v)
{
    if (L<=l&&r<=R)
    {
        cov[rt]+=v;
        sum[rt]+=v;
        return ;
    }
    PushDown(rt);
    int m=(l+r)>>1;
    if (L<=m) update(rt<<1,l,m,L,R,v);
    if (R>m)  update(rt<<1|1,m+1,r,L,R,v);
    PushUp(rt);
}

int main()
{
    LL x,y;
    int n,i,w,h,c,nx,ny,ans;
    while (~scanf("%d %d %d",&n,&w,&h))
    {
        for (i=0;i<n;i++)
        {
            scanf("%I64d %I64d %d",&x,&y,&c);
            X[i]=x; X[n+i]=x+w-1;
            line[i]=Line(x,x+w-1,y,c);
            line[n+i]=Line(x,x+w-1,y+h-1,-c);
        }
        sort(X,X+n*2);
        sort(line,line+n*2);
        for (nx=0,i=1;i<n*2;i++)
            if (X[i]!=X[i-1]) X[++nx]=X[i];
        memset(sum,0,sizeof(sum));
        memset(cov,0,sizeof(cov));
        for (ans=i=0;i<n*2;i++)
        {
            int L=Fin(line[i].lx,nx);
            int R=Fin(line[i].rx,nx);
            if (L<=R) update(1,0,nx,L,R,line[i].f);
            ans=Max(ans,sum[1]);
        }
        printf("%d\n",ans);
    }
    return 0;
}

离线:


#include<cstdio>
#include<iostream>
#include<cstring>
#include<algorithm>
#define ls rt<<1
#define rs rt<<1|1
#define lson l,m,ls
#define rson m+1,r,rs
using namespace std;

const int mm=10001;
const int mn=mm<<2;
struct star
{
    int x,y,c;
    bool operator < (const star &cmp) const {
        return x<cmp.x;
    }
}g[mm];

int dly[mn],sum[mn];
int y[mm],m;

int Max(int a1,int a2)
{
    return a1>a2?a1:a2;
}

void pushdown(int rt)
{
    sum[ls]+=dly[rt];
    sum[rs]+=dly[rt];
    dly[ls]+=dly[rt];
    dly[rs]+=dly[rt];
    dly[rt]=0;
}

void pushup(int rt)
{
    sum[rt]=Max(sum[ls],sum[rs]);
}

void updata(int L,long long R,int val,int l,int r,int rt)
{
    if(L<=y[l]&&R>=y[r])
    {
        sum[rt]+=val;
        dly[rt]+=val;
        return;
    }
    if(dly[rt])pushdown(rt);
    int m=(l+r)>>1;
    if(L<=y[m])updata(L,R,val,lson);
    if(R>=y[m+1])updata(L,R,val,rson);
    pushup(rt);
}

int main()
{
    int i,j,k,n,w,h,ans;
    while(~scanf("%d%d%d",&n,&w,&h))
    {
        for(i=0;i<n;++i)
        {
            scanf("%d%d%d",&g[i].x,&g[i].y,&g[i].c);
            y[i]=g[i].y;
        }
        sort(y,y+n);
        sort(g,g+n);
        for(m=i=0;i<n;++i)
            if(y[m]!=y[i])y[++m]=y[i];
        memset(dly,0,sizeof(dly));
        memset(sum,0,sizeof(sum));
        for(ans=j=i=0;i<n;++i)
        {
            updata(g[i].y,(long long)g[i].y+h-1,g[i].c,0,m,1);
            while(j<=i&&g[i].x-g[j].x+1>w)
            {
                updata(g[j].y,(long long)g[j].y+h-1,-g[j].c,0,m,1);
                ++j;
            }
            ans=Max(ans,sum[1]);
        }
        printf("%d\n",ans);
    }
    return 0;
}



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值