bzoj 3196二逼平衡树 线段树套平衡树

比较裸的树套树,对于区间K值bz上有一道裸题,详见题解http://www.cnblogs.com/BLADEVIL/p/3455336.html(其实题解也不是很详细)

//By BLADEVIL

type

    rec                            =record

        left, right, root        :longint;

    end;



var

    n, m                        :longint;

    a                            :array[0..100100] of longint;

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

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

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

    tot                            :longint;

    

function min(a,b:longint):longint;

begin

    if a>b then min:=b else min:=a;

end;



function max(a,b:longint):longint;

begin

    if a>b then max:=a else max:=b;

end;

    

procedure left_rotate(var t:longint);

var

    k                            :longint;

begin

    k:=b_right[t];

    b_right[t]:=b_left[k];

    b_left[k]:=t;

    b_size[k]:=b_size[t];

    b_size[t]:=b_size[b_left[t]]+b_size[b_right[t]]+1;

    t:=k;

end;



procedure right_rotate(var t:longint);

var

    k                            :longint;

begin

    k:=b_left[t];

    b_left[t]:=b_right[k];

    b_right[k]:=t;

    b_size[k]:=b_size[t];

    b_size[t]:=b_size[b_left[t]]+b_size[b_right[t]]+1;

    t:=k;

end;

    

procedure maintain(var t:longint;flag:boolean);

begin

    if not flag then 

    begin

        if b_size[b_left[b_left[t]]]>b_size[b_right[t]] then 

            right_rotate(t) else 

        if b_size[b_right[b_left[t]]]>b_size[b_right[t]] then 

        begin

            left_rotate(b_left[t]);

            right_rotate(t);

        end else exit;

    end else 

    begin

        if b_size[b_right[b_right[t]]]>b_size[b_left[t]] then 

            left_rotate(t) else 

        if b_size[b_left[b_right[t]]]>b_size[b_left[t]] then 

        begin

            right_rotate(b_right[t]);

            left_rotate(t);

        end else exit;

    end;

    maintain(b_left[t],false);

    maintain(b_right[t],true);

    maintain(t,true);

    maintain(t,false);

end;

    

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

begin

    if t=0 then 

    begin

        inc(tot);

        t:=tot;

        b_left[t]:=0;

        b_right[t]:=0;

        b_size[t]:=1;

        b_key[t]:=v;

    end else 

    begin

        inc(b_size[t]);

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

        maintain(t,v>=b_key[t]);

    end;

end;



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

begin

    dec(b_size[t]);

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

    begin

        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]:=delete(b_left[t],v+1);

    end else 

        if v>b_key[t] then delete:=delete(b_right[t],v) else delete:=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,a[i]);

    if l=r then exit;

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

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

end;



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

begin

    if t=0 then exit(0);

    if v<=b_key[t] then 

        b_rank:=b_rank(b_left[t],v) else 

        b_rank:=b_rank(b_right[t],v)+b_size[b_left[t]]+1;

end;

    

procedure init;

var

    i                            :longint;

    

begin

    read(n,m);

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

    build(1,1,n);

end;



function rank(x,l,r,y:longint):longint;

var

    mid                            :longint;

begin

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

    begin

        rank:=b_rank(t[x].root,y);

        exit;

    end;

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

    if mid<l then rank:=rank(x*2+1,l,r,y) else 

    if mid>=r then rank:=rank(x*2,l,r,y) else 

    rank:=rank(x*2,l,mid,y)+rank(x*2+1,mid+1,r,y);

end;



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

begin

    writeln(rank(1,l,r,x)+1);

end;



procedure change(x,y,z,c:longint);

var

    mid                            :longint;

begin

    mid:=delete(t[x].root,c);

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

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

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

    if y>mid then change(x*2+1,y,z,c) else 

        change(x*2,y,z,c);

end;



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

begin

    if t=0 then exit(-1);

    if v<=b_key[t] then b_pred:=b_pred(b_left[t],v) else 

    begin

        b_pred:=b_pred(b_right[t],v);

        if b_pred=-1 then b_pred:=b_key[t];

    end;

end;



function pred(x,l,r,y:longint):longint;

var

    mid                            :longint;

begin

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

    begin

        pred:=b_pred(t[x].root,y);

        exit;

    end;

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

    if mid<l then pred:=pred(x*2+1,l,r,y) else 

    if mid>=r then pred:=pred(x*2,l,r,y) else 

    pred:=max(pred(x*2,l,mid,y),pred(x*2+1,mid+1,r,y));

end;



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

begin

    writeln(pred(1,l,r,x));

end;



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

begin

    if t=0 then exit(maxlongint);

    if v>=b_key[t] then b_succ:=b_succ(b_right[t],v) else 

    begin

        b_succ:=b_succ(b_left[t],v);

        if b_succ=maxlongint then b_succ:=b_key[t];

    end;

end;



function succ(x,l,r,y:longint):longint;

var

    mid                            :longint;

begin

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

    begin

        succ:=b_succ(t[x].root,y);

        exit;

    end;

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

    if mid<l then succ:=succ(x*2+1,l,r,y) else 

    if mid>=r then succ:=succ(x*2,l,r,y) else

        succ:=min(succ(x*2,l,mid,y),succ(x*2+1,mid+1,r,y));

end;



procedure askselect(a,b,x:longint);

var

    mid                            :longint;

    ans                            :longint;

    l, r                        :longint;

    xx                            :longint;

begin

    l:=0; r:=1000000000;

    while l<=r do 

    begin

        mid:=(l+r) div 2;

        xx:=rank(1,a,b,mid)+1;

        if xx<=x then 

        begin

            ans:=mid;

            l:=mid+1;

        end else r:=mid-1;

    end;

    if rank(1,a,b,ans)=x then ans:=succ(1,l,r,ans-1) else ans:=ans;

    writeln(ans);

end;



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

begin

    writeln(succ(1,l,r,x));

end;



procedure main;

var

    i                            :longint;

    k, l, r, x                    :longint;

    

begin

    for i:=1 to m do 

    begin

        read(k);

        if k=1 then 

        begin

            read(l,r,x);

            askrank(l,r,x);

        end else 

        if k=2 then 

        begin

            read(l,r,x);

            askselect(l,r,x);

        end else

        if k=3 then 

        begin

            read(l,x);

            change(1,l,x,a[l]);

            a[l]:=x;

        end else 

        if k=4 then

        begin

            read(l,r,x);

            askpred(l,r,x);

        end else 

        if k=5 then 

        begin

            read(l,r,x);

            asksucc(l,r,x);

        end;

    end;

end;



begin

    init;

    main;

end.

 

你可能感兴趣的:(线段树)