poj 2182 Lost Cows
题目大意
N头牛从1到N编号(2<=N<=8000)。这N头牛排成一列,但编号并不一定是递增的。农夫John统计出以下数据:对于每一头牛,排在它前面的编号比它小的牛的数量。你要计算出每个位置上牛的编号。
分析
一眼可以看出如果第n头牛前有x头比他小,那他的编号就是x+1。以此类推…
线段树:ad记录该区间目前还剩ad个空位,每一次插入的时候,如果该节点左儿子ad>=pos,那么只要在左儿子找就可以了否则要在右儿子中找,此时pos改为pos-左儿子ad。
代码
type pnode=^tnode; tnode=record lc,rc:pnode; c:longint; end; var t:pnode; i,j,k:longint; x,y:longint; n,m:longint; a,ans:array[1..10000] of longint; procedure neww(var t:pnode); begin if t=nil then begin new(t); t^.c:=0; t^.lc:=nil; t^.rc:=nil; end; end; procedure insert(var t:pnode; l,r,cr:longint); var i,j,k:longint; mid:longint; begin with t^ do begin c:=cr; mid:=(l+r) div 2; if l=r then exit; neww(lc); neww(rc); insert(lc,l,mid,mid); insert(rc,mid+1,r,cr); end; end; function find(var t:pnode;l,r,cr:longint):longint; var mid:longint; begin t^.c:=t^.c-1; with t^ do begin if (lc=nil) and (rc=nil) then exit(l); mid:=(l+r) div 2; if lc^.c>=cr then find:=find(lc,l,mid,cr) else find:=find(rc,mid+1,r,cr+mid-Lc^.c); end; end; begin readln(n); fillchar(t,sizeof(t),0); neww(t); insert(t,1,n,n); for i:=1 to n-1 do readln(a[i]); for i:=n-1 downto 1 do ans[i]:=find(t,1,n,a[i]+1); writeln(find(t,1,n,1)); for i:=1 to n-1 do writeln(ans[i]); end.