[GRYZ2015]阿Q的停车场

题目描述

刚拿到驾照的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

样例输出








3

数据范围

对30%的数据 n<=1000 ,m<=1000 
对60%的数据 n<=200000,m<=2000 
对100%的数据n,m<=200000,车的编号小于等于 10^6

思路

30%  

  第一边做打了一个爆搜,维护停车场和距离最大值两个数组,进出车辆各自维护,进车的时候两个指针分别指向左右端点,维护值即为原值和更新值中较小的;出车的时候因为不知道此时的值是谁赋给它的,所有把空车位全部填满重来一遍。

const ma=200000;

var f:array[1..ma] of longint;
    a:array[1..ma] of longint;
    n,m,k,x,y,num,ss,kk:longint;

function min(x,y:longint):longint;
begin
    if x<y then exit(x) else exit(y);
end;

procedure intt;
begin
    assign(input,‘park.in‘);
    assign(output,‘park.out‘);
    reset(input);
    rewrite(output);
end;

procedure outt;
begin
    close(input);
    close(output);
end;

function update1(x:longint):longint;
var i,j,k,sum,num:longint;
begin
    i:=x;j:=x;
    while i>=1 do
        begin
            if a[i]=0 then
                f[i]:=min(f[i],abs(x-i));
            dec(i);
        end;
    while j<=n do
        begin
            if a[j]=0 then
                f[j]:=min(f[j],abs(x-j));
            inc(j);
        end;
    num:=0;sum:=0;
    for i:=1 to n do
        if (a[i]=0)and(f[i]>sum) then
            begin
                sum:=f[i];
                num:=i;
            end;
    exit(num);
end;
//car in

function update2(x:longint):longint;
var i,j,num,sum:longint;
begin
    for i:=1 to n do
        if a[i]=0 then f[i]:=2139062143;
    for i:=1 to n do
        if a[i]<>0 then
            for j:=1 to n do
                if a[j]=0 then
                    f[j]:=min(f[j],abs(i-j));
    num:=0;sum:=0;
    for i:=1 to n do
        if (a[i]=0)and(f[i]>sum) then
            begin
                sum:=f[i];
                num:=i;
            end;
    exit(num);
end;
//car out

begin
    intt;
    fillchar(f,sizeof(f),127);
    fillchar(a,sizeof(a),0);
    readln(n,m);
    for k:=1 to m do
        begin
            readln(x,y);
            if k=1 then
                begin
                    a[1]:=y;
                    writeln(1);
                    ss:=update1(1);
                    continue;
                end;
            if x=1 then
                begin
                    writeln(ss);
                    a[ss]:=y;
                    f[ss]:=2139062143;
                    ss:=update1(ss);
                    continue;
                end;
            if x=2 then
                begin
                    for kk:=1 to n do
                        if a[kk]=y then
                            begin
                                a[kk]:=0;
                                f[kk]:=2139062143;
                                ss:=update2(kk);
                                break;
                            end;
                    continue;
                end;
        end;
    outt;
end.

45% 

  XYD维护了某车两侧的空车位,我也不知道是怎么维护的,反正也是爆搜。

program dddlk;
var a,l,r:array[0..200001]of longint;
    f:array[1..200000]of boolean;
    b:array[1..1000000]of longint;
    n,m,i,j,a1,a2,ans,b1,max,b2:longint;
begin
  assign(input,‘park.in‘);
  assign(output,‘park.out‘);
  reset(input);
  rewrite(output);
  ans:=1;
  read(n,m);
  a[0]:=-300000;
  a[n+1]:=-300000;
  l[0]:=-300000;
  r[n+1]:=500000;
  for i:=1 to n do
    a[i]:=maxlongint;
  for i:=1 to m do
    begin
      read(a1,a2);
      if a1=1
        then
          begin
            writeln(ans);
            b[a2]:=ans;
            f[ans]:=true;
            a[ans]:=0;
            r[ans]:=ans;
            l[ans]:=ans;
            b1:=ans-1;
            while(b1>0)and(not f[b1])do
              begin
                if a[b1]>ans-b1
                  then a[b1]:=ans-b1;
                r[b1]:=ans;
                dec(b1);
              end;
            b1:=ans+1;
            while(b1<n+1)and(not f[b1])do
              begin
                if a[b1]>b1-ans
                  then a[b1]:=b1-ans;
                l[b1]:=ans;
                inc(b1);
              end;
            max:=a[1];
            ans:=1;
            for j:=2 to n do
              if a[j]>max
                then
                  begin
                    max:=a[j];
                    ans:=j;
                  end;
          end
        else
          begin
            b2:=b[a2];
            b1:=b2-1;
            f[b2]:=false;
            while(b1>0)and(not f[b1])do
              begin
                r[b1]:=r[b2+1];
                if b1-l[b1]>r[b1]-b1
                  then a[b1]:=r[b1]-b1
                  else a[b1]:=b1-l[b1];
                dec(b1);
              end;
            b1:=b2+1;
            while(b1<n+1)and(not f[b1])do
              begin
                l[b1]:=l[b2-1];
                if b1-l[b1]>r[b1]-b1
                  then a[b1]:=r[b1]-b1
                  else a[b1]:=b1-l[b1];
                inc(b1);
              end;
            l[b2]:=l[b2-1];
            r[b2]:=r[b2+1];
            if b2-l[b2]>r[b2]-b2
              then a[b2]:=r[b2]-b2
              else a[b2]:=b2-l[b2];
            max:=a[1];
            for j:=2 to n do
              if a[j]>max
                then
                  begin
                    max:=a[j];
                    ans:=j;
                  end;
          end;
    end;
  close(input);
  close(output);
end.

60%

  不晓得这个怎么搞

100%

  用线段树实现。(据某位大神说,可以用堆来做。然而我并不会)用线段树还是相对简单的。首先我们对区间[1..n]开一课线段树。对于每一个节点,维护4个值。分别是l,r,mid,p。l表示在当前结点线段树所在区间,最左边的车停的位置。同理,r表示做右边的车所停的位置。mid表示在这个小区间[l,r]中的紧邻的两辆车的最长距离除以2后的值。p表示取得mid值是所在的紧邻的两辆车的中间位置,也就是在[l,r]中的答案值。

  对于 1 询问:访问线段树的第一个节点,我们比较l-1,n-r,mid的值哪个更大,就选哪个,它们的答案依次是1,n,mid。假设我们求得的位置是car[x]。然后访问[car[x],car[x]]所在的线段树的叶子节点,初始化它的值,然后回溯,进行合并。对于h[x].l与h[x].r可以通过两个儿子的l,r信息得出。对于h[x].mid值,首先在左右儿子的mid值中去一个最大的值。其次考虑一种情况,就是夹在两个线段之间的距离,可以通过(h[x+x+1].l-h[x+x].r) div 2 的值得出在于mid进行比较,然后p就随着mid的值的更新而更新。 
对于2询问:访问询问车所在的位置,直接将它的叶子节点[car[x],car[x]]删除,然后回溯时,再做一次合并操作。即可

AC做法:http://blog.csdn.net/liuyuanzhe0515/article/details/47414221

const   maxc=1000005;maxn=200005;
type    node=record
        l,r,mid,p:longint;
    end;
var i,j,k,m,n,ch,num,sum:longint;
    car:array[1..maxc] of longint;
    h:array[1..4*maxn] of node;
procedure merger(x:longint);
var t:longint;
begin
    if h[x+x].l>0 then h[x].l:=h[x+x].l else h[x].l:=h[x+x+1].l;
    if h[x+x+1].r>0 then h[x].r:=h[x+x+1].r else h[x].r:=h[x+x].r;
    h[x].mid:=h[x+x].mid;
    h[x].p:=h[x+x].p;
    if (h[x+x+1].l>0) and (h[x+x].r>0) then begin
        t:=(h[x+x+1].l-h[x+x].r) div 2;
        if t>h[x].mid then begin
            h[x].mid:=t;
            h[x].p:=(h[x+x+1].l+h[x+x].r) div 2;
        end;
        if h[x+x+1].mid>h[x].mid then begin
            h[x].mid:=h[x+x+1].mid;
            h[x].p:=h[x+x+1].p;
        end;
    end;
end;
procedure work(x,l,r,num,kind:longint);
var mid:longint;
begin
    if l=r then begin
        if kind=2 then begin
            h[x].l:=0;h[x].r:=0;
            h[x].mid:=0;h[x].p:=0;
        end else begin
            h[x].l:=l;h[x].r:=r;
            h[x].mid:=0;h[x].p:=0;
        end;
        exit;
    end;
    mid:=(l+r)>>1;
    if num<=mid then work(x+x,l,mid,num,kind) else work(x+x+1,mid+1,r,num,kind);
    merger(x);
end;
begin
    readln(n,m);
    for i:=1 to m do begin
        readln(ch,num);
        if ch=1 then begin
            if h[1].l=0 then begin
                car[num]:=1;
            end else begin
                sum:=-maxlongint;
                if h[1].l-1>sum then begin
                    sum:=h[1].l-1;
                    car[num]:=1;
                end;
                if h[1].mid>sum then begin
                    sum:=h[1].mid;
                    car[num]:=h[1].p;
                end;
                if n-h[1].r>sum then begin
                    sum:=n-h[1].r;
                    car[num]:=n;
                end;
            end;
            writeln(car[num]);
            work(1,1,n,car[num],1);
        end else begin
            work(1,1,n,car[num],2);
        end;
    end;
end.

时间: 2024-10-20 05:45:04

[GRYZ2015]阿Q的停车场的相关文章

阿Q的停车场

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

考前模拟冲刺2

1. 足球联赛(soccer.pas/c/cpp ) 题目描述: 巴蜀中学新一季的足球联赛开幕了.足球联赛有 n只球队参赛,每赛季,每只球队要与其他球队各赛两场,主客各一场,赢一场得 3 分,输一场不得分,平局两只队伍各得一分. 英勇无畏的小鸿是机房的主力前锋,她总能在关键时刻踢出一些匪夷所思的妙球.但是很可惜,她过早的燃烧完了她的职业生涯,不过作为一个能够 Burning 的 girl,她的能力不止如此,她还能预测这个赛季所有球队的比赛结果. 虽然她能准确预测所有比赛的结果,但是其实她不怎么厉

2017.11.8 Noip2017 考前模拟赛

----------------------------------T1---------------------------------- ——>足球联赛 题目描述 巴蜀中学新一季的足球联赛开幕了. 足球联赛有 n 只球队参赛,每赛季,每只球队要与其他球队各赛两场,主客各一场,赢一场得 3 分,输一场不得分,平局两只队伍各得一分. 英勇无畏的小鸿是机房的主力前锋, 她总能在关键时刻踢出一些匪夷所思的妙球. 但是很可惜,她过早的燃烧完了她的职业生涯,不过作为一个能够 Burning 的 girl

关于“停车场问题”所做的总结

数据结构第二次上机作业.“停车场问题” 主要考察问题: 栈: 初始化栈 判断栈满 入栈 出栈 队列: 初始化链队列 判断链队列是否为空 链队列入队 链队列出队 总结细节问题: string函数只能在C++函数中使用: 使用时要包含头文件#include<iostream>   #include<string> 要使用栈或者队列,用之前必须初始化栈或者队列: 在定义一个指针时,必须给他一个空间: 以下是源代码: 1 #include <stdio.h> 2 #includ

refresh的停车场(栈和队列的STL)

refresh的停车场 Time Limit: 1000ms   Memory limit: 65536K  有疑问?点这里^_^ 题目描述 refresh最近发了一笔横财,开了一家停车场.由于土地有限,停车场内停车数量有限,但是要求进停车场的车辆过多.当停车场满时,要进入的车辆会进入便道等待,最先进入便道的车辆会优先 进入停车场,而且停车场的结构要求只出去的车辆必须是停车场中最后进去的车辆.现告诉你停车场容量N以及命令数M,以及一些命令(Add num 表示车牌号为num的车辆要进入停车场或便

refresh的停车场(模拟)

refresh的停车场 Time Limit: 1000MS Memory limit: 65536K 题目描述 refresh最近发了一笔横财,开了一家停车场.由于土地有限,停车场内停车数量有限,但是要求进停车场的车辆过多.当停车场满时,要进入的车辆会进入便道等待,最先进入便道的车辆会优先 进入停车场,而且停车场的结构要求只出去的车辆必须是停车场中最后进去的车辆.现告诉你停车场容量N以及命令数M,以及一些命令(Add num 表示车牌号为num的车辆要进入停车场或便道, Del 表示停车场中出

7.6 停车场管理

7-7 ParkCharge.c 1 #include "stdio.h" 2 #include "time.h" 3 #define MAXNUM 5 //停车场车位数 4 #define PRICE 2.0 //每小时收费 5 typedef struct car //定义车的结构体 6 { 7 char num[10]; //车牌号(最多10个字节) 8 struct tm intime; //进入时间 9 struct tm outtime; //离开时间

数据结构之停车场

程序设计思想: 1.首先定义一个数据类型包含车牌号和进去的时间,这两个车的信息. 2.定义栈一用来模仿停车场的入栈函数(其中包含入队函数,栈满则入队),栈二用来储存栈一出来元素的入栈函数. 3.两个栈的有共同的出栈函数. 4.定义队列(模仿便道)的入队与出队函数 5.在主函数中调用时间函数用来记录时间 6.定义两个栈和一个队列,同时初始化. 7.提示用户输入车牌号,利用while不停的输入(输入的同时记下输入时间),直到输入end为止. 8.在while循环中给用户提供进车,出车,结束的三个选择

SDUT -refresh的停车场(栈和队列)

题目描写叙述 refresh近期发了一笔横財,开了一家停车场.因为土地有限,停车场内停车数量有限,可是要求进停车场的车辆过多. 当停车场满时,要进入的车辆会进入便道等待.最先进入便道的车辆会优先 进入停车场,并且停车场的结构要求仅仅出去的车辆必须是停车场中最后进去的车辆. 现告诉你停车场容量N以及命令数M,以及一些命令(Add num 表示车牌号为num的车辆要进入停车场或便道. Del 表示停车场中出去了一辆车,Out 表示便道最前面的车辆不再等待,放弃进入停车场).如果便道内的车辆不超过10