• poj2182


    首先容易知道,最后一个数是最容易确定的,于是从后往前确定

    对于位置j,它的数就是1~n中剩余数的第a[j]+1小的数

    这当然可以用平衡数做,复杂度为O(nlogn)

    有没有更简洁得算法?树状数组+二分

     1 var v:array[0..8010] of boolean;
     2     c,ans,a:array[0..8010] of longint;
     3     i,j,n:longint;
     4 function lowbit(x:longint):longint;
     5   begin
     6     exit(x and (-x));
     7   end;
     8 
     9 function sum(x:longint):longint;
    10   begin
    11     sum:=0;
    12     while x>0 do
    13     begin
    14       sum:=sum+c[x];
    15       x:=x-lowbit(x);
    16     end;
    17   end;
    18 
    19 function kth(t:longint):longint;
    20   var l,r,m,p:longint;
    21   begin
    22     l:=1;
    23     r:=n;
    24     while l<=r do
    25     begin
    26       m:=(l+r) shr 1;
    27       p:=sum(m);       //统计二分得到的这个数前面有几个比它小的
    28       if (p=t) and not v[m] then exit(m);   //注意不要忘记判断这个数是否存在
    29       if p<t then l:=m+1 else r:=m-1;
    30     end;
    31   end;
    32 
    33 procedure add(x,w:longint);
    34   begin
    35     while x<=n do
    36     begin
    37       c[x]:=c[x]+w;
    38       x:=x+lowbit(x);
    39     end;
    40   end;
    41 
    42 begin
    43   readln(n);
    44   for i:=2 to n do
    45     readln(a[i]);
    46   for i:=1 to n do    //初始化
    47     add(i,1);
    48   fillchar(v,sizeof(v),false);
    49   for i:=n downto 1 do
    50   begin
    51     ans[i]:=kth(a[i]+1);  //确定当前位置
    52     v[ans[i]]:=true;      //删除这个数
    53     add(ans[i],-1);
    54   end;
    55   for i:=1 to n do
    56     writeln(ans[i]);
    57 end.
    View Code

    总的复杂度为O(n*logn*logn)虽然慢了一点,但是编程复杂度大大下降

  • 相关阅读:
    古罗马子串加密
    读《大道至简》有感(四)
    类与对象(作业)
    读《大道至简》有感(三)
    JAVA 加减乘除
    JAVA第三周作业
    【JAVA】数字相加
    读《大道至简》有感(二)
    1.8站立会议之个人
    1.7站立会议之个人
  • 原文地址:https://www.cnblogs.com/phile/p/4473281.html
Copyright © 2020-2023  润新知