题目大意:
有N个数值,他们要依次插入,每次输入a[i],b[i]表示b[i]插入到第a[i]个位置,即b[i]占用了第a[i]+1个位置,这个位置以后的人(包括这个位置的人)全都后退一格,求最后的整个队列的位置。
1 ≤ N ≤ 200,000
PS:每一组数据中有多组输入。
题解:
线段树:
根据题目可以发现,如果逆着插入每一个插队的人的话,是不会影响他前后的人(包括在他之前插队的人)的,也就是说最后的结果是不会改变的,所以我们逆序插入,然后
1.建树,tree[i]表示当前第i个结点所代表的区间[l,r]内还剩余多少个格子没有被覆盖。
2.pos表示要插入到当前区间[l,r]的第pos个位置(已经被占用的位置pos不累加),每一次插入的时候,如果左子树已经插的没有位置了即tree[p*2] < pos,这时候就插入到右子树上,并且pos要减去左子树占用的格子数。
初值:
tree[i]【代表区间[l,r]】=r-l+1
var
ans,tree:array [0..1000001] of longint;
p,q:array [0..200001] of longint;
i,j,n:longint;
procedure build(p,l,r:longint);
var
mid:longint;
begin
mid:=(l+r) div 2;
if l=r then tree[p]:=1
else begin
build(p * 2,l,mid);
build(p*2+1,mid+1,r);
tree[p]:=tree[p*2]+tree[p*2+1];
end;
end;
procedure insert(p,l,r,pos:longint);
var
mid:longint;
begin
dec(tree[p]);
mid:=(l+r) div 2;
if l=r then ans[r]:=q[i]
else begin
if tree[p*2]>=pos
then insert(p * 2,l,mid,pos)
else insert(p*2+1,mid+1,r,pos-tree[p*2]);
end;
end;
begin
while not eof do
begin
readln(n);
build(1,1,n);
for i:=1 to n do readln(p[i],q[i]);
for i:=n downto 1 do
insert(1,1,n,p[i]+1);
for i:=1 to n do write(ans[i],' ');
writeln;
end;
end.