bzoj 3295 树套树

比较裸,可以有好多的优化,比如根本没有删除的点没有加在树套树中的必要,预处理

出来每个不会被删除的值可以减少不少时间,也可以写成树状数组套平衡树,都会快很多

/**************************************************************

    Problem: 3295

    User: BLADEVIL

    Language: Pascal

    Result: Accepted

    Time:11088 ms

    Memory:52180 kb

****************************************************************/

 

//By BLADEVIL

type

    rec                     =record

        left, right, root   :longint;

    end;

      

var

    n, m                    :longint;

    high, cur               :array[0..200100] of longint;

    t                       :array[0..300040] of rec;

    b_left, b_right, b_key  :array[0..3000010] of longint;

    b_size                  :array[0..3000010] of longint;

    tot                     :longint;

    ans                     :int64;

      

procedure swap(var a,b:longint);

var

    c                       :longint;

begin

    c:=a; a:=b; b:=c;

end;

      

procedure insert(var t:longint;v:longint);

begin

    if t=0 then

    begin

        inc(tot);

        t:=tot;

        b_size[t]:=1;

        b_left[t]:=0;

        b_right[t]:=0;

        b_key[t]:=v;

    end else

    begin

        inc(b_size[t]);

        if v<b_key[t] then insert(b_left[t],v) else insert(b_right[t],v);

    end;

end;

  

function b_delete(var t:longint;v:longint):longint;

begin

    dec(b_size[t]);

    if (b_key[t]=v) or (v>b_key[t]) and (b_right[t]=0) or (v<b_key[t]) and (b_left[t]=0) then

    begin

        b_delete:=b_key[t];

        if (b_left[t]=0) or (b_right[t]=0) then t:=b_left[t]+b_right[t] else

            b_key[t]:=b_delete(b_left[t],v+1);

    end else

        if v>=b_key[t] then exit(b_delete(b_right[t],v)) else exit(b_delete(b_left[t],v));

end;

      

procedure build(x,l,r:longint);

var

    mid                     :longint;

    i                       :longint;

begin

    t[x].left:=l; t[x].right:=r; t[x].root:=0;

    for i:=l to r do insert(t[x].root,high[i]);

    if l=r then exit;

    with t[x] do mid:=(left+right) div 2;

    build(2*x,l,mid);

    build(2*x+1,mid+1,r);

end;

  

function b_less(var t:longint;v:longint):longint;

begin

    if t=0 then exit(0);

    if b_key[t]>=v then exit(b_less(b_left[t],v)) else

        exit(b_size[b_left[t]]+1+b_less(b_right[t],v));

end;

  

function less(x,l,r,v:longint):longint;

var

    mid                     :longint;

begin

    if (t[x].left=l) and (t[x].right=r) then

        exit(b_less(t[x].root,v));

    with t[x] do mid:=(left+right) div 2;

    if mid<l then exit(less(2*x+1,l,r,v)) else

    if mid>=r then exit(less(2*x,l,r,v)) else

        exit(less(2*x,l,mid,v)+less(2*x+1,mid+1,r,v));

end;

  

function b_greater(var t:longint; v:longint):longint;

begin

    if t=0 then exit(0);

    if b_key[t]<=v then exit(b_greater(b_right[t],v)) else

        exit(b_size[b_right[t]]+1+b_greater(b_left[t],v));

end;

  

function greater(x,l,r,v:longint):longint;

var

    mid                     :longint;

begin

    if (t[x].left=l) and (t[x].right=r) then

        exit(b_greater(t[x].root,v));

    with t[x] do mid:=(left+right) div 2;

    if mid<l then exit(greater(2*x+1,l,r,v)) else

    if mid>=r then exit(greater(2*x,l,r,v)) else

        exit(greater(2*x,l,mid,v)+greater(2*x+1,mid+1,r,v));

end;

  

procedure change(x,y,v:longint);

var

    mid                     :longint;

begin

    insert(t[x].root,v);

    if (t[x].left=t[x].right) then exit;

    with t[x] do mid:=(left+right) div 2;

    if mid<y then change(2*x+1,y,v) else change(2*x,y,v);

end;

  

procedure delete(x,y,v:longint);

var

    mid                     :longint;

begin

    b_delete(t[x].root,v);

    if (t[x].left=t[x].right) then exit;

    with t[x] do mid:=(left+right) div 2;

    if mid<y then delete(2*x+1,y,v) else delete(2*x,y,v);

end;

  

procedure init;

var

    i                       :longint;

begin

    read(n,m);

    for i:=1 to n do read(high[i]);

    for i:=1 to n do cur[high[i]]:=i;

    build(1,1,n); 

end;

  

procedure main;

var

    i                       :longint;

    x, y                    :longint;

      

begin 

    for i:=1 to n-1 do

        ans:=ans+less(1,i+1,n,high[i]);

    for i:=1 to m do

    begin

        writeln(ans);

        read(x);

        y:=cur[x];

        delete(1,y,x);

        if y<>1 then ans:=ans-greater(1,1,y-1,x);

        if y<>n then ans:=ans-less(1,y+1,n,x);

    end;

end;

  

begin

    init;

    main;

end.

 

你可能感兴趣的:(ZOJ)