zkw线段树 逆推 poj2828

动态插入在序列中任意位置,询问最终序列。

可以用块状链表做,但同样可以用编程复杂度和时间复杂度更优的zkw线段树做,只需思维上的转换。

思路来自罗雨屏

从正面来看,这题实在很难处理,每个数的位置都处于动态变化中,但从反面来看,每个数的位置其实都是确定的,它要求放在第x个位置,其实就是逆推时,当前第x个为空格的位置,我们只需维护当前区间有多少空格,便可在log(n)时间快速确定数的位置,而且实现比块状链表容易得多,但是块状链表也有其优秀的地方,可以做大部分序列维护的事情,而且这些功能可以按照自己选择添加,只是编程复杂度比较高,理论时间复杂度也高于平衡树。

var n,m1:longint; sum,d:array[1..524288]of longint; a,b:array[1..2000000]of longint; procedure inset(x,y:longint); var i,l,r:longint; begin i:=1; while i<m1+1 do begin dec(sum[i]);l:=i<<1;r:=i<<1+1; if sum[l]>x then i:=l else begin i:=r;x:=x-sum[l] end end; dec(sum[i]);d[i]:=y end; procedure change(x:longint); var i:longint; begin i:=x+m1; while i<>0 do begin inc(sum[i]);i:=i>>1 end; end; procedure origin; var i:longint; begin fillchar(d,sizeof(d),0); fillchar(sum,sizeof(sum),0); m1:=1; while m1<n+2 do m1:=m1<<1;m1:=m1-1; for i:=1 to n do change(i) end; procedure init; var i:longint; begin readln(n); origin; for i:=1 to n do readln(a[i],b[i]); for i:=n downto 1 do inset(a[i],b[i]); for i:=1 to n do write(d[i+m1],' '); writeln end; begin while not(seekeof) do init end. 

你可能感兴趣的:(zkw线段树 逆推 poj2828)