CodeForces 46D 停车场 数据结构+线段树+寻找位置+维护空位+区间赋值

CodeForces 46D 停车场

Time Limit:2000MS    Memory Limit:262144KB    64bit IO Format:%I64d & %I64u

Description

有一个长为L的停车道,坐标从0开始,车辆停放时车头朝向正方向,且距离车头f范围内和距离车尾b范围内不能有其它车辆。
有两种操作:“1    a”,有1辆长度为a的车开进来找停车位。如果能找到输出最小的起始位置,否则输出-1.
                         “2    a”,第i个操作中开进来的车开出去了(保证第i个操作是1操作)

Input

第一行3个 整数L,b 和f(10 ≤ L ≤ 100000, 1 ≤ b, f ≤ 100).

第二行1个 整数n(1 ≤ n ≤ 100)表示询问个数。

然后n个询问。

 

Output

每个"1 a"询问输出一个数字占一行。如果没有停车位输出-1,否则输出车尾的坐标(坐标从0开始)。

Sample Input

 

30 1 2
6
1 5
1 4
1 5
2 2
1 5
1 4
30 1 1
6
1 5
1 4
1 5
2 2
1 5
1 4
10 1 1
1
1 12

Sample Output

0
6
11
17
23
0
6
11
17
6
-1

解题思路:
这题和hotle相似,几乎就是改改代码就对了,可以之前我还没发现,自己写了半天老是首尾处理不好
然后别人提醒我直接在长度首尾添加上车的前后距离就可以了,真是,这样简单多了,反正首部一定
要放车,尾部也可以正常处理。
1,这题的主要的目的就是让你找到一个最靠左的距离,停一部指定距离的车,满足车前车后的距离
2,若成功停车就返回车尾的位置,否则返回-1
3,然后就是通过线段树找位置咯,找到满足这样长度的区间,线段树要做的就是区间合并维护空位
4,然后细心一点咯。

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
const int maxn = 100005 ;
int tlen[maxn<<2] ;///tlen表示该区间可用的区间的最大长度
int rlen[maxn<<2] ;///rlen表示一个区间从最右端开始可用的且连续的最大长度
int llen[maxn<<2] ;///llen表示一个区间从最左端开始可用的且连续的最大长度
int setv[maxn<<2] ;
struct node{
    int op ;
    int x;
    int l;
    int r;
};
void pushdown(int l,int r,int rt){
    if(setv[rt]!=-1){
        setv[rt<<1] = setv[rt] ;
        setv[rt<<1|1] = setv[rt] ;
        int m = (l+r)>>1 ;
        tlen[rt<<1] = llen[rt<<1] = rlen[rt<<1] = setv[rt]*(m-l+1) ;
        tlen[rt<<1|1] = llen[rt<<1|1] = rlen[rt<<1|1] = setv[rt]*(r-m) ;
        setv[rt] = -1 ;
    }
    return ;
}
void pushup(int l,int r,int rt){
    int m  = (l+r)>>1 ;
    if(llen[rt<<1]==(m-l+1))llen[rt] = llen[rt<<1]+llen[rt<<1|1];
    else llen[rt] = llen[rt<<1] ;
    if(rlen[rt<<1|1]==(r-m))rlen[rt] = rlen[rt<<1|1]+rlen[rt<<1] ;
    else rlen[rt] = rlen[rt<<1|1] ;
    tlen[rt] = max(tlen[rt<<1],tlen[rt<<1|1]);
    tlen[rt] = max(tlen[rt],rlen[rt<<1]+llen[rt<<1|1]);
    return ;
}
void build(int l,int r,int rt){
    int m = (l+r)>>1 ;
    if(l==r){
        tlen[rt] = 1 ;
        llen[rt] = 1 ;
        rlen[rt] = 1 ;
        return ;
    }
    build(lson) ;
    build(rson) ;
    pushup(l,r,rt) ;
}
int query(int p,int l,int r,int rt ){///找p个连续座位
    if(l==r){
        return l;
    }
    int m = (r+l)>>1 ;
    pushdown(l,r,rt) ;
    if(tlen[rt]>=p){
        if(tlen[rt<<1]>=p){
            return query(p,lson) ;
        }else if(rlen[rt<<1]+llen[rt<<1|1]>=p){//&&rlen[rt<<1]>0){
            //return query(min(p,rlen[rt<<1]),lson) ;
            return m-rlen[rt<<1]+1 ;
        }else{
            return query(p,rson) ;
        }
        //return 0;
    }else{
        return 0;
    }
}
void update(int L,int R,int s,int l,int r,int rt){
    if(L<=l&&r<=R){
        setv[rt] = s ;
        tlen[rt] = llen[rt] = rlen[rt] = s*(r-l+1) ;
        return ;
    }
    pushdown(l,r,rt) ;
    int m = (l+r)>>1 ;
    if(L<=m)update(L,R,s,lson) ;
    if(R>m)update(L,R,s,rson) ;
    pushup(l,r,rt) ;
}
node arry[115] ;
int L,b,f ;
int main(){
    int n,m;
    //freopen("in.txt","r",stdin) ;
    //freopen("out2.txt","w",stdout) ;
    while(~scanf("%d%d%d",&L,&b,&f)){
        memset(tlen,0,sizeof(tlen)) ;
        memset(rlen,0,sizeof(rlen)) ;
        memset(llen,0,sizeof(llen)) ;
        memset(setv,-1,sizeof(setv)) ;
        build(1,L+b+f,1) ;
        n = L+b+f ;
        scanf("%d",&m);
        for(int i=0;i<m;i++){
            scanf("%d%d",&arry[i].op,&arry[i].x);
        }
        for(int i=0;i<m;i++){
            if(arry[i].op==1){
                int w  = arry[i].x+b+f;
                if(w>tlen[1]){
                    puts("-1") ;
                    continue ;
                }
                int index = query(w,1,n,1) ;
                printf("%d\n",index-1);
                arry[i].l = index+b ;
                arry[i].r = index+b+arry[i].x ;
                if(index!=0){
                    update(index+b,index+b+arry[i].x-1,0,1,n,1) ;
                }
            }else{
                update(arry[arry[i].x-1].l,arry[arry[i].x-1].r,1,1,n,1) ;
            }
        }
    }
    return 0;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值