Codeforces 46 D Parking Lot(线段树区间更新模板题)

本文介绍了一个关于停车场管理的问题,通过使用线段树数据结构进行高效的空间分配与查询。具体包括如何通过线段树实现车辆的停放与离开操作,并详细解释了算法的具体实现细节。

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

题目地址
题意:有长度为n米的停车场,停车的要求是要与前面一辆车至少隔a米,和后一辆车至少隔b米(只要符合要求就可以停入,不管之后会不会打破这个要求。PS:我就是想了好久没有想通),有m个操作,有两种操作类型:

  1. 1 x 把长度为x米的车停入停车场(一定要符合停车要求)
  2. 2 x 将第x个操作中停入的车开出

思路:把停车场扩建为n+a+b,把每辆车都变为x+a+b来查找,这样就可以直接停车了,但是车子还是只有x的长度,所以在update的时候是用了pos+a~pos+a+y-1(为什么要减一,因为他的边可以重复利用)去更新,但是因为第一辆车多占用了a个,所以输出位置的时候要减去a就是pos了
PS:要这题模板的戳这里

#include <iostream>
#include <cstring>
#include <string>
#include <queue>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <cmath>
#include <cstdio>
#include <algorithm>
#define N 50010
#define LL long long
#define inf 0x3f3f3f3f
#define gol ans<<1
#define gor ans<<1|1
#define lson l,mid,ans<<1
#define rson mid+1,r,ans<<1|1
using namespace std;
const LL mod = 1e9 + 7;
const double eps = 1e-9;
struct node {
    int l, r, lazy;
    int llen, rlen, maxlen;
}tree[N<<2];
struct nope {
    int l, r;
}now;
map<int, nope> mapp;
struct Segment__Tree {
    void pushDown(int ans, int num) {
        if (tree[ans].lazy != -1) {
            tree[gol].lazy = tree[ans].lazy;
            tree[gor].lazy = tree[ans].lazy;
            tree[gol].llen = tree[gol].rlen = tree[gol].maxlen = (tree[ans].lazy ? 0 : num - (num >> 1));
            tree[gor].llen = tree[gor].rlen = tree[gor].maxlen = (tree[ans].lazy ? 0 : (num >> 1));
            tree[ans].lazy = -1;
        }
    }
    void pushUp(int ans, int num) {
        tree[ans].llen = tree[gol].llen;
        tree[ans].rlen = tree[gor].rlen;
        tree[ans].maxlen = max(tree[gol].maxlen, tree[gor].maxlen);
        if (tree[ans].llen == num - (num >> 1)) {
            tree[ans].llen += tree[gor].llen;
        }
        if (tree[ans].rlen == num >> 1) {
            tree[ans].rlen += tree[gol].rlen;
        }
        tree[ans].maxlen = max(tree[ans].maxlen, tree[gol].rlen + tree[gor].llen);
    }
    void build(int l, int r, int ans) {
        tree[ans].l = l;
        tree[ans].r = r;
        tree[ans].lazy = -1;
        tree[ans].llen = tree[ans].rlen = tree[ans].maxlen = r - l + 1;
        if (l == r) {
            return;
        }
        int mid = (l + r) >> 1;
        build(lson);
        build(rson);
    }
    void updata(int l, int r, int ans, int num) {//更新区间
        if (l <= tree[ans].l&&r >= tree[ans].r) {
            tree[ans].lazy = num;
            tree[ans].llen = tree[ans].rlen = tree[ans].maxlen = (num ? 0 : tree[ans].r - tree[ans].l + 1);
            return;
        }
        pushDown(ans, tree[ans].r - tree[ans].l + 1);
        int mid = (tree[ans].l + tree[ans].r) >> 1;
        if (l <= mid) {
            updata(l, r, gol, num);
        }
        if (mid < r) {
            updata(l, r, gor, num);
        }
        pushUp(ans, tree[ans].r - tree[ans].l + 1);
    }
    int query(int ans, int num) {//查询长度为num的空闲区间
        if (tree[ans].l == tree[ans].r) {
            return tree[ans].l;
        }
        pushDown(ans, tree[ans].r - tree[ans].l + 1);
        int mid = (tree[ans].l + tree[ans].r) >> 1;
        if (tree[gol].maxlen >= num) {
            return query(gol, num);
        }
        if (tree[gol].rlen + tree[gor].llen >= num) {
            return mid - tree[gol].rlen + 1;
        }
        return query(gor, num);
    }
};
int main() {
    cin.sync_with_stdio(false);
    int n, m;
    int a, b;
    int x, y;
    Segment__Tree trees;
    while (cin >> n >> a >> b) {
        cin >> m;
        mapp.clear();
        n = n + a + b;
        trees.build(1, n, 1);
        for (int i = 1; i <= m; i++) {
            cin >> x >> y;
            if (x == 1) {
                if (tree[1].maxlen < y + a + b) {
                    cout << -1 << endl;
                }
                else {
                    int pos = trees.query(1, y + a + b);
                    now.l = pos + a;
                    now.r = now.l + y - 1;
                    mapp[i]=now;
                    trees.updata(now.l, now.r, 1, 1);
                    cout << pos - 1 << endl;
                }
            }
            else {
                trees.updata(mapp[y].l, mapp[y].r, 1, 0);
            }
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值