zoukankan      html  css  js  c++  java
  • [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.
    View Code

    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.
    View Code

    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.
    View Code
  • 相关阅读:
    Ubuntu 下安装Mongodb
    iOS 配置支付宝
    Spring异步任务处理,@Async的配置和使用
    [Tue, 11 Aug 2015 ~ Mon, 17 Aug 2015] Deep Learning in arxiv
    linux-shell脚本命令之awk
    字符串写入文件
    UVa 10773
    Flex下拉框
    DELPHI dbgrid 选中的是第几行 怎么判断?
    delphi 取得数据集某字段值的六种方法
  • 原文地址:https://www.cnblogs.com/yangqingli/p/4927698.html
Copyright © 2011-2022 走看看