【POJ2828】Buy Tickets(线段树)

时间:2021-08-24 19:23:34

题意:有一个输入序列,每次操作要把b[i]插入到第a[i]个,在第a[i]个后面的要后移,问最后序列。

n<=200000

思路:顺序来只能用splay维护

考虑倒序,对于插入到第K个位置,在线段树二分第K个0的位置,类似于主席树

将其插入后将这个位置修改为已经有数

单点修改

 var t:array[..]of longint;
a,b,c:array[..]of longint;
n,i,k:longint; procedure pushup(p:longint);
begin
t[p]:=t[p<<]+t[p<<+];
end; function query(l,r,k,p:longint):longint;
var mid:longint;
begin
if l=r then exit(l);
mid:=(l+r)>>;
if t[p<<]>=k then exit(query(l,mid,k,p<<))
else exit(query(mid+,r,k-t[p<<],p<<+));
pushup(p);
end; procedure update(l,r,k,p:longint);
var mid:longint;
begin
if (l=k)and(r=k) then
begin
dec(t[p]); exit;
end;
mid:=(l+r)>>;
if k<=mid then update(l,mid,k,p<<)
else update(mid+,r,k,p<<+);
pushup(p);
end; procedure build(l,r,p:longint);
var mid:longint;
begin
if l=r then
begin
t[p]:=; exit;
end;
mid:=(l+r)>>;
build(l,mid,p<<);
build(mid+,r,p<<+);
pushup(p);
end; begin
assign(input,'poj2828.in'); reset(input);
assign(output,'poj2828.out'); rewrite(output);
while not eof do
begin
readln(n);
if n= then break;
for i:= to n<< do t[i]:=;
fillchar(c,sizeof(c),);
for i:= to n do
begin
read(a[i],b[i]);
inc(a[i]);
end;
build(,n,);
for i:=n downto do
begin
k:=query(,n,a[i],);
c[k]:=b[i];
update(,n,k,);
end;
for i:= to n- do write(c[i],' ');
write(c[n]);
writeln;
end; close(input);
close(output);
end.