cf 219E parking lot 线段树

本文介绍了一种通过数据结构和算法解决停车场中寻找最优停车位置的问题。具体实现使用了区间覆盖的方法,通过维护区间最大值、左端点最大值及右端点最大值等信息,实现了高效更新和查询。该算法能快速找到距离两侧车辆最远的空位,并支持车辆的离开操作。

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

空的标为1。两个操作。

将车停在离左右两边最近车最远的地方。如果有两个位置,输出编号小的位置。

编号为id的车离开停车场。

做题过程:

       杂么什么都说跟那个hotel有点像。。。Orz。。。。

      这个很有特色的就是push_up和查询了。

#include <iostream>
#include <cstring>
#include <cstdio>
#define lson l, m , rt << 1
#define rson m + 1, r, rt << 1 | 1
#define ls rt << 1
#define rs rt << 1 | 1
#define havem int m = (l + r ) >> 1
#define maxn 222222
using namespace std;
int op,id,pos[10 * maxn],n,m;
int lsum[maxn << 2], rsum[maxn << 2], msum[maxn << 2], beg[maxn << 2];
void build(int l, int r, int rt){
    lsum[rt] = rsum[rt] = msum[rt] = r - l + 1;
    beg[rt] = l;
    if(l == r) return ;
    havem;
    build(lson); build(rson);
}
void push_up(int rt, int l, int r){
    int m = r - l + 1;
    lsum[rt] = lsum[ls] + (lsum[ls] == (m - (m >> 1)) ? lsum[rs]: 0);
    rsum[rt] = rsum[rs] + (rsum[rs] == (m >> 1) ? rsum[ls] : 0);
    msum[rt] = msum[ls] ;  beg[rt] = beg[ls];//先初始化为左边的

    if(rsum[ls] + lsum[rs] > msum[rt] + 1 || (rsum[ls] + lsum[rs] > msum[rt] && msum[rt] % 2 == 0)){
        msum[rt] = rsum[ls] + lsum[rs];
        beg[rt] = ( (l + r) >> 1 ) - rsum[ls] + 1;
    }

    if(msum[rs] > msum[rt] + 1 || (msum[rs] > msum[rt] && msum[rt] % 2 == 0)){
        msum[rt] = msum[rs];
        beg[rt] = beg[rs];
    }
}
void update(int pos, int val, int l , int r, int rt){
    if(l == r){
        lsum[rt] = rsum[rt] = msum[rt] = (val == 0 ? 0 : 1);
        return ;
    }havem;
    if(pos <= m) update(pos,val, lson);
    else update(pos,val,rson);
    push_up(rt, l , r);
}
int findpos(){
    int final = 1, len = msum[1], s = beg[1];
    if(s + len - 1 == n && s != 1){
        final = n;
    }else{
        int mmax = lsum[1] - 1;
        if((len - 1) / 2 > mmax){
            mmax = (len - 1) / 2;
            final = s + (len - 1) / 2;
        }
        if(rsum[1] - 1 > mmax){
            mmax = rsum[1] - 1;
            final = n;
        }
    }
    return final;
}
int main(){
    scanf("%d%d",&n,&m);
    build(1,n,1);
    for(int i = 0; i < m; i ++){
        scanf("%d%d",&op,&id);
        if(op == 1){
            int ret = findpos();
            printf("%d\n",ret);
            update(ret, 0, 1, n, 1);
            pos[id] = ret;
        }else{
            update(pos[id], 1, 1, n, 1);
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值