停车场

题目描述
刚拿到驾照的 KJ 总喜欢开着车到处兜风,玩完了再把车停到阿 Q 的停车场里,虽然她对自己停车的水平很有信心,但她还是不放心其他人的停车水平,尤其是 Kelukin。于是,她每次都把自己的爱车停在距离其它车最远的一个车位。KJ 觉得自己这样的策略非常科学,于是她开始想:在一个停车场中有一排车位,从左到右编号为 1 到 n,初始时全部是
空的。有若干汽车,进出停车场共 m 次。对于每辆进入停车场的汽车,会选择与其它车距离最小值最大的一个车位,若有多个符合条件,选择最左边一个。KJ 想着想着就睡着了,在她一旁的 Kelukin 想帮她完成这个心愿,但是他又非常的懒,不愿意自己动手,于是就把这个问题就留给了你:在 KJ 理想的阿 Q 的停车场中,给你车辆进出的操作序列,依次输
出每辆车的车位编号。

输入
第一行,两个整数 n 和 m,表示停车场大小和操作数;
接下来 m 行,每行两个整数 F 和 x
F 是 1 表示编号为 x 的车进停车场;
F 是 2 表示编号为 x 的车出停车场;
保证操作合法,即:
出停车场的车一定目前仍在停车场里;
停车场内的车不会超过 n;

输出
对于所有操作 1,输出一个整数,表示该车车位的编号

样例输入
7 11
1 15
1 123123
1 3
1 5
2 123123
2 15
1 21
2 3
1 6
1 7
1 8

样例输出
1
7
4
2
7
4
1
3

  • 翻译一下题目,就是叫你把一个[1,n]的区间每次找到“最长”的那一段,输出那段的中间点(停车的位置),特殊判断[1,p]:停车在1 和 [q,n]:停车在n.
  • 方法一:用线段树做,每次停车,将停车位置上的权值视为0,每次开走,将停车位置上的权值视为1. 用上传更新(我这样叫它:push_pu())的方法更新每段区间内的最长线段mx和最长线段的起始位置mxpos。为了更新最长线段,需要记录区间左端开始的最长线段lmx和右段开始的最长线段rmx。就像hotel那道题一样。特殊的是,最长线段mx不必再包含区间两端的lmx和rmx,因为并没什么用。最后Quary的时候要特殊判断。
  • 方法二:用优先队列做,把停车后截成的小线段进队列,判断当前的最大线段是否合理用树状数组。在用链表记录一下车左右的车的位置,就差不多了。
#include<cstdio>
#define MAXN 200000
#define MAXNUM 2000000

struct node{
    int l,r;
    int lmx,rmx,mx,mxpos;
}tree[MAXN*4+100];
int n,m,car[MAXNUM+10];

void build(int i,int l,int r)
{
    tree[i].l=l,tree[i].r=r;
    tree[i].lmx=tree[i].rmx=tree[i].mx=r-l+1;
    tree[i].mxpos=l;
    if(l==r) return ;
    int mid=(l+r)/2;
    build(i*2,l,mid);
    build(i*2+1,mid+1,r);
}

int Weight(int len)
{
    if(!len) return 0;
    return (len-1)/2+1;
}
void Adjust(int i,int len,int st)
{
    if(!len) return ;
    int g=Weight(tree[i].mx),h=Weight(len);
    if(g<h) tree[i].mx=len,tree[i].mxpos=st;
    else if(g==h && st<tree[i].mxpos) tree[i].mxpos=st;
}
void push_up(int i)
{
    tree[i].lmx=tree[i*2].lmx,tree[i].rmx=tree[i*2+1].rmx;
    if(tree[i].lmx==tree[i*2].r-tree[i*2].l+1)
        tree[i].lmx+=tree[i*2+1].lmx;
    if(tree[i].rmx==tree[i*2+1].r-tree[i*2+1].l+1)
        tree[i].rmx+=tree[i*2].rmx;

    //标记好mx=0,impossible;mx不用一并包含lmx和rmx
    tree[i].mxpos=0,tree[i].mx=0;
    Adjust(i,tree[i*2].rmx+tree[i*2+1].lmx,tree[i*2].r-tree[i*2].rmx+1);
    Adjust(i,tree[i*2].mx,tree[i*2].mxpos);
    Adjust(i,tree[i*2+1].mx,tree[i*2+1].mxpos);
}
void insert(int i,int inpos,int d)
{
    if(tree[i].l==inpos && tree[i].r==inpos){
        tree[i].lmx=tree[i].rmx=tree[i].mx=d;
        if(d)
            tree[i].mxpos=tree[i].l;
        else
            tree[i].mxpos=0;
        return ;
    }

    int mid=(tree[i].l+tree[i].r)/2;
    if(inpos<=mid) insert(i*2,inpos,d);
    else insert(i*2+1,inpos,d);

    push_up(i);
}
int Quary()
{
    int len=(tree[1].mx-1)/2+1,ret=(tree[1].mxpos*2+tree[1].mx-1)/2;
    if(tree[1].lmx>=len) ret=1;
    else if(tree[1].rmx>len) ret=n;
    return ret;
}
int main()
{
    int p,num,inpos;
    scanf("%d%d",&n,&m);
    build(1,1,n);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&p,&num);
        if(p==1){
            inpos=Quary();
            printf("%d\n",inpos);
            car[num]=inpos;
            insert(1,inpos,0);
        }
        else{
            inpos=car[num];
            insert(1,inpos,1);
            car[num]=0;
        }
    }
}

错误代码:还不知道怎么错了!!!!!!!!

#include<cstdio>
#define MAXN 200000
#define MAXNUM 2000000

struct node{
    int l,r;
    int lmax,rmax,maxx,mxpos;
}tree[MAXN*4+100];
int n,m,car[MAXNUM+10];

void build(int i,int l,int r)
{
    tree[i].l=l,tree[i].r=r;
    tree[i].lmax=tree[i].rmax=tree[i].maxx=r-l+1;
    tree[i].mxpos=l;
    if(l==r) return ;
    int mid=(l+r)/2;
    build(i*2,l,mid);
    build(i*2+1,mid+1,r);
}
void revise(int i,int len,int pos)
{
    tree[i].lmax=tree[i].rmax=tree[i].maxx=len;
    tree[i].mxpos=pos;
}
int Interval(node a)
{
    return a.r-a.l+1;
}
int Weight(int l,int len)
{
    if(!len) return -1;
    if(l==1) return len;
    if(l+len-1==n) return len;
    return (len-1)/2+1;
}
void Adjust(int i,int tmp,int tmpl)
{
    int a=Weight(tree[i].mxpos,tree[i].maxx),b=Weight(tmpl,tmp);
    if(a<b)
        tree[i].maxx=tmp,tree[i].mxpos=tmpl;
    else if(a==b && tree[i].mxpos>tmpl)
        tree[i].mxpos=tmpl;
}
void insert(int i,int inpos,int d)
{
    if(tree[i].l==inpos && tree[i].r==inpos){
        if(d) revise(i,1,tree[i].l);
        else revise(i,0,0);
        return ;
    }

    int mid=(tree[i].l+tree[i].r)/2;
    if(inpos<=mid) insert(i*2,inpos,d);
    else insert(i*2+1,inpos,d);

    tree[i].lmax=tree[i*2].lmax,tree[i].rmax=tree[i*2+1].rmax;
    if(tree[i].lmax==Interval(tree[i*2]))
        tree[i].lmax+=tree[i*2+1].lmax;
    if(tree[i].rmax==Interval(tree[i*2+1]))
        tree[i].rmax+=tree[i*2].rmax;

    tree[i].maxx=tree[i].lmax;
    tree[i].mxpos=tree[i].l;

    Adjust(i,tree[i].rmax,tree[i].r-tree[i].rmax+1);
    Adjust(i,tree[i*2].rmax+tree[i*2+1].lmax,tree[i*2].r-tree[i*2].rmax+1);
    Adjust(i,tree[i*2].maxx,tree[i*2].mxpos);
    Adjust(i,tree[i*2+1].maxx,tree[i*2+1].mxpos);

}
int Quary()
{
    int len=(tree[1].maxx-1)/2+1,ret=(tree[1].mxpos*2+tree[1].maxx-1)/2;
    if(tree[1].lmax>=len) len=tree[1].lmax,ret=1;
    if(tree[1].rmax>len) ret=n;
    return ret;
}
int main()
{
    int p,num;
    scanf("%d%d",&n,&m);
    build(1,1,n);
    for(int i=1;i<=m;i++){
        scanf("%d%d",&p,&num);
        if(p==1){
            int pos=Quary();
            printf("%d\n",pos);
            car[num]=pos;
            insert(1,pos,0);
        }
        else{
            int pos=car[num];
            insert(1,pos,1);
            car[num]=0;
        }
    }
}

转载于:https://www.cnblogs.com/katarinayuan/p/6572862.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
设有一个可以停放n辆汽车的狭长停车场,它只有一个大门可以供车辆进出。车辆按到达停车场时间的早晚依次从停车场最里向大门口处停放(最先到达的第一辆车放在停车场的最里面)。如果停车场已放满n辆车,则后来的车只能在停车场大门外的便道上等待,一旦停车场内有车开走,则排在便道上的第一辆车就进入停车场停车场内如有某辆车要开走,在它之后进入停车场的车都必须先退出停车场为它让路,待其开出停车场后,这些车辆再依原来的次序进场。每辆车在离开停车场时,都应根据它在停车场内停留的时间长短交费。如果停留在便道上的车未进停车场就要离去,允许其离去,不收停车费,并且仍然保持在便道上等待的车辆次序。编制一程序模拟该停车场的管理。(2) 实现要求:要求程序输出每辆车到达后的停车位置(停车场或便道上),以及某辆车离开停车场时应交纳的费用和它在停车场内停留的时间。(2) 实现提示:汽车的模拟输入信息格式可以是:(到达/离去,汽车牌照号码,到达/离去的时刻)。例如,(’A’,1,5)表示1号牌照车在5时刻到达,而(’D’,5,20)表示5号牌照车在20时刻离去。整个程序可以在输入信息为(’E’,0,0)时结束。本题可用顺序存储结构和链式存储结构来实现。本人的一个数据结构课程设计(用C++源码实现,供大家学习参考之用,有不妥之处望指正)

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值