BZOJ2957 楼房重建

本文介绍了一种使用线段树解决BZOJ2957楼房重建问题的方法,通过维护线段树中的最大斜率和可见线段数量,实现了对二维平面上特定线段的有效统计。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

BZOJ2957 楼房重建
题目大意

给定二维平面中的垂直于x轴正半轴的线段,求与原点(0,0)连线中不与任何线段相交的线条条数

思路

线段树维护
cnt[rt]rt所表示的线段[l,r]中可见的线段条数
sum[rt]rt表示的线段[l,r]中最大的斜率
对于当前修改的线段,其左边的原先保存的答案依然可行
对于其右边的线段,划分成左右子区间,如果左子区间的最大斜率比更新值要小,直接统计右端点答案,否则统计左子区间的答案,再加上右子区间的答案,注意右子区间的答案为cnt[rt]cnt[rt<<1](因为要加上左子区间的约束条件)

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;

typedef long long LL;


const int MAXN = 100000+10;

double sum[MAXN<<2];
LL cnt[MAXN<<2],n,m,x,y;


LL calc(int rt,int l,int r,double h)
{
    if(l==r)    return sum[rt]>h;
    int mid=(l+r)>>1;
    if(sum[rt<<1]<=h)   return calc(rt<<1|1,mid+1,r,h);
    return calc(rt<<1,l,mid,rt)+cnt[rt]-cnt[rt<<1];
}


void updata(double val,int x,int l,int r,int rt)
{
    if(l==r)
    {
        sum[rt]=val;
        cnt[rt]=1;
        return ;
    }
    int mid=(l+r)>>1;
    if(x<=mid)  updata(val,x,l,mid,rt<<1);
    else updata(val,x,mid+1,r,rt<<1|1);
    sum[rt]=max(sum[rt<<1],sum[rt<<1|1]);
    cnt[rt]=cnt[rt<<1]+calc(rt<<1|1,mid+1,r,sum[rt<<1]);
}

int main()
{
    scanf("%lld%lld",&n,&m);
    for(int i=1;i<=m;i++)
    {
        scanf("%lld%lld",&x,&y);
        updata( (double)y/x,x,1,n,1 );
        printf("%lld\n",cnt[1]);
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值