CF-46D-Parking Lot(线段树)

Nowadays it is becoming increasingly difficult to park a car in cities successfully. Let‘s imagine a segment of a street as long as L meters along which
a parking lot is located. Drivers should park their cars strictly parallel to the pavement on the right side of the street (remember that in the country the authors of the tasks come from the driving is right side!). Every driver when parking wants to leave
for themselves some extra space to move their car freely, that‘s why a driver is looking for a place where the distance between his car and the one behind his will be no less than b meters
and the distance between his car and the one in front of his will be no less than f meters (if there‘s no car behind then the car can be parked at the
parking lot segment edge; the same is true for the case when there‘re no cars parked in front of the car). Let‘s introduce an axis of coordinates along the pavement. Let the parking lot begin at point 0 and end at point L.
The drivers drive in the direction of the coordinates‘ increasing and look for the earliest place (with the smallest possible coordinate) where they can park the car. In case there‘s no such place, the driver drives on searching for his perfect peaceful haven.
Sometimes some cars leave the street and free some space for parking. Considering that there never are two moving cars on a street at a time write a program that can use the data on the drivers, entering the street hoping to park there and the drivers leaving
it, to model the process and determine a parking lot space for each car.

Input

The first line contains three integers Lb и f (10?≤?L?≤?100000,?1?≤?b,?f?≤?100).
The second line contains an integer n (1?≤?n?≤?100)
that indicates the number of requests the program has got. Every request is described on a single line and is given by two numbers. The first number represents the request type. If the request type is equal to 1,
then in that case the second number indicates the length of a car (in meters) that enters the street looking for a place to park. And if the request type is equal to 2,
then the second number identifies the number of such a request (starting with 1) that the car whose arrival to the parking lot was described by a request with
this number, leaves the parking lot. It is guaranteed that that car was parked at the moment the request of the 2 type was made. The lengths of cars are integers
from 1 to1000.

Output

For every request of the 1 type print number -1 on
the single line if the corresponding car couldn‘t find place to park along the street. Otherwise, print a single number equal to the distance between the back of the car in its parked position and the beginning of the parking lot zone.

Sample test(s)

input

30 1 2
6
1 5
1 4
1 5
2 2
1 5
1 4

output

0
6
11
17
23

input

30 1 1
6
1 5
1 4
1 5
2 2
1 5
1 4

output

0
6
11
17
6

input

10 1 1
1
1 12

output

-1

思路:维护区间左边和右边的空地长度还有区间最大的连续空地长度即可。

#include <stdio.h>
#define max(A,B)(A>B?A:B)

struct
{
    int l,r;
}qur[100];

int mx[400005],ls[400005],rs[400005],att[400005];

void build(int idx,int s,int e)
{
    if(s!=e)
    {
        int mid=(s+e)>>1;

        build(idx<<1,s,mid);
        build(idx<<1|1,mid+1,e);
    }

    mx[idx]=ls[idx]=rs[idx]=e-s+1;
    att[idx]=-1;
}

void update(int idx,int s,int e,int l,int r,int val)
{
    if(l==s && e==r)
    {
        att[idx]=val;

        mx[idx]=ls[idx]=rs[idx]=(e-s+1)*val;

        return;
    }

    int mid=(s+e)>>1;

    if(att[idx]!=-1)
    {
        mx[idx<<1]=ls[idx<<1]=rs[idx<<1]=(mid-s+1)*att[idx];
        mx[idx<<1|1]=ls[idx<<1|1]=rs[idx<<1|1]=(e-mid)*att[idx];

        att[idx<<1]=att[idx<<1|1]=att[idx];

        att[idx]=-1;
    }

    if(r<=mid) update(idx<<1,s,mid,l,r,val);
    else if(l>mid) update(idx<<1|1,mid+1,e,l,r,val);
    else
    {
        update(idx<<1,s,mid,l,mid,val);
        update(idx<<1|1,mid+1,e,mid+1,r,val);
    }

    ls[idx]=ls[idx<<1];
    rs[idx]=rs[idx<<1|1];
    mx[idx]=max(mx[idx<<1],mx[idx<<1|1]);

    if(ls[idx]==mid-s+1) ls[idx]+=ls[idx<<1|1];
    if(rs[idx]==e-mid) rs[idx]+=rs[idx<<1];

    mx[idx]=max(rs[idx<<1]+ls[idx<<1|1],mx[idx]);
}

int query(int idx,int s,int e,int val)
{
    int mid=(s+e)>>1;

    if(att[idx]!=-1)
    {
        mx[idx<<1]=ls[idx<<1]=rs[idx<<1]=(mid-s+1)*att[idx];
        mx[idx<<1|1]=ls[idx<<1|1]=rs[idx<<1|1]=(e-mid)*att[idx];

        att[idx<<1]=att[idx<<1|1]=att[idx];

        att[idx]=-1;
    }

    if(mx[idx<<1]>=val) return query(idx<<1,s,mid,val);
    else if(rs[idx<<1]+ls[idx<<1|1]>=val) return mid-rs[idx<<1]+1;
    else if(mx[idx<<1|1]>=val) return query(idx<<1|1,mid+1,e,val);
    else return -1;
}

int main()
{
    int n,b,f,q,i,type,val,ans;

    while(~scanf("%d%d%d%d",&n,&b,&f,&q))
    {
        n+=b+f-1;

        build(1,0,n);

        for(i=1;i<=q;i++)
        {
            scanf("%d%d",&type,&val);

            if(type==1)
            {
                ans=query(1,0,n,val+b+f);

                printf("%d\n",ans);

                if(ans==-1) continue;

                qur[i].l=ans+b;
                qur[i].r=ans+b+val-1;

                update(1,0,n,qur[i].l,qur[i].r,0);
            }
            else update(1,0,n,qur[val].l,qur[val].r,1);
        }
    }
}
时间: 2024-12-28 19:35:45

CF-46D-Parking Lot(线段树)的相关文章

Codeforces 46D Parking Lot(线段树)

题目链接:Codeforces 46D Parking Lot 题目大意:一个街道,长为N,每辆车停进来的时候必须和前面间隔B米,和后面间隔F米,现在用两种操作,1是停进来一个长为x的车,2是第x辆车开走. 解题思路:区间合并,建一颗长度为N + B + F的线段树,然后每次停车进去的时候都查询x + B + F的区间,然后修改的时候只修改x的长度. #include <cstdio> #include <cstring> #include <algorithm> us

CF 46 D Parking Lot(线段树区间合并)

Description Nowadays it is becoming increasingly difficult to park a car in cities successfully. Let's imagine a segment of a street as long as L meters along which a parking lot is located. Drivers should park their cars strictly parallel to the pav

【线段树】【树状数组】【CF 121E】幸运数列

1922. [CF 121E]幸运数列 ★★★ 输入文件:cf121e.in 输出文件:cf121e.out 简单对比 时间限制:3 s 内存限制:256 MB [题目描述] 对于欧洲人来说,"幸运数"是指那些十进制只由4或7组成的数.财务员Petya需要维护一个支持如下操作的整数数列: add l r d - 表示将[l, r]区间内的所有数加上一个正整数d(). count l r - 统计[l, r]区间内有多少个"幸运数".() 请你帮助Petya实现它.

CF#52 C Circular RMQ (线段树区间更新)

Description You are given circular array a0,?a1,?...,?an?-?1. There are two types of operations with it: inc(lf,?rg,?v) - this operation increases each element on the segment [lf,?rg] (inclusively) by v; rmq(lf,?rg) - this operation returns minimal v

CF 338E, 线段树

这道题真是太伤节奏了,做完之后好几天没动弹了. 题目大意:给你两个数组a.b,a长b短,对于以a每个位置开头与b等长的连续子序列,我们询问是否有这样一个匹配方式让子序列每个数和b中每个数一一对应相加且和大于给定的常数h. 解:没有想明白,去看官解没弄懂出题人是怎么分块瞎搞的.搜了一下题解,发现有一个更巧妙的解法,首先我们对b排序不会影响到结果,然后对于某个数,他在排序后的b里的合法匹配方案一定是连续的一段,这样就转化成了线段问题.对于Bn(从小到大排序的B数组),我们可知必须子序列里有n个数和他

CF(438D) The Child and Sequence(线段树)

题意:对数列有三种操作: Print operation l,?r. Picks should write down the value of . Modulo operation l,?r,?x. Picks should perform assignment a[i]?=?a[i] mod x for each i (l?≤?i?≤?r). Set operation k,?x. Picks should set the value of a[k] to x (in other words

(困难) CF 484E Sign on Fence,整体二分+线段树

Bizon the Champion has recently finished painting his wood fence. The fence consists of a sequence of n panels of 1 meter width and of arbitrary height. The i-th panel's height is hi meters. The adjacent planks follow without a gap between them. Afte

CF 633G 线段树+bitset

大意是一棵树两种操作,第一种是某一节点子树所有值+v,第二种问子树中节点模m出现了多少种m以内的质数. 第一种操作非常熟悉了,把每个节点dfs过程中的pre和post做出来,对序列做线段树.维护取模也不是问题.第二种操作,可以利用bitset记录质数出现情况.所以整个线段树需要维护bitset的信息. 对于某一个bitset x,如果子树所有值需要加y,则x=(x<<y)|(x>>(m-y)) 一开始写挂了几次,有一点没注意到,因为我bitset直接全都是1000,而不是m,所以上

CF 498D 线段树

大意是有n段路,每一段路有个值a,通过每一端路需要1s,如果通过这一段路时刻t为a的倍数,则需要等待1s再走,也就是需要2s通过. 比较头疼的就是相邻两个数之间会因为数字不同制约,一开始想a的范围是2-6,处理这几个数字互相之间的关系,还是想岔了. 正解应当是开60个线段树,因为2-6的LCM是60,也就是所有数字模2-6,结果的循环节长度为60.所以如果从i到j,开始时刻如果为0,则答案一定与开始时刻为60相同. 第x个线段树某个节点范围如果是i和j,维护的便是开始时刻模60为x的情况下,从i

Cf 444C DZY Loves Colors(线段树)

DZY loves colors, and he enjoys painting. On a colorful day, DZY gets a colorful ribbon, which consists of n units (they are numbered from 1 to n from left to right). The color of thei-th unit of the ribbon is i at first. It is colorful enough, but w