首先容易知道,最后一个数是最容易确定的,于是从后往前确定
对于位置j,它的数就是1~n中剩余数的第a[j]+1小的数
这当然可以用平衡数做,复杂度为O(nlogn)
有没有更简洁得算法?树状数组+二分
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
![](https://images.cnblogs.com/OutliningIndicators/ExpandedBlockStart.gif)
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 begin11 sum:=0;12 while x>0 do13 begin14 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 begin22 l:=1;23 r:=n;24 while l<=r do25 begin26 m:=(l+r) shr 1;27 p:=sum(m); //统计二分得到的这个数前面有几个比它小的28 if (p=t) and not v[m] then exit(m); //注意不要忘记判断这个数是否存在29 if p
总的复杂度为O(n*logn*logn)虽然慢了一点,但是编程复杂度大大下降