POJ P2182 Lost Cows

题目大意:
有N个数,为1~N,给出N-1个a[i]表示前i个数有多少个数比当前的数要小,因为a[1]=0所以输入从a[2]开始,即输入a[2],a[3]……a[n-1],a[n]。

2 <= N <= 8,000

题解:
跟这题有点类似:
http://blog.csdn.net/gx_man_vip/article/details/71640465
线段树:
首先我们可以发现从最后一个数开始插入,对于他的整个结果就不会产生改变。
然后我们倒着插入数进入线段树:
首先建树:
tree[i]表示它所代表的区间[l,r]有多少个没有被填入数,即空白~。
然后插入:
pos表示要插入到当前区间[l,r]的第pos个位置,注意这里所说的第pos个位置,是除去已经占用了的位置后的,每一次插入的时候,如果左子树已经插的没有位置了即tree[p*2] < pos,这时候就插入到右子树上,并且pos要减去左子树占用的格子数。
pos=a[i]+1,因为每一次插入因为前面有a[i]个小于自己的。

var
    ans,tree:array [0..100001] of longint;
    p:array [0..8001] of longint;
    i,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[i]:=l
            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
    readln(n);
    build(1,1,n);
    for i:=2 to n do readln(p[i]);
    for i:=n downto 1 do
        insert(1,1,n,p[i]+1);
    for i:=1 to n do writeln(ans[i]);
end.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值