• bzoj 1901 线段树套平衡树+二分答案查询


    我们就建一颗线段树,线段树的每一个节点都是一颗平衡树,对于每个询问来说,我们就二分答案,

    查询每个二分到的mid在这个区间里的rank,然后就行了

    /**************************************************************
        Problem: 1901
        User: BLADEVIL
        Language: Pascal
        Result: Accepted
        Time:3220 ms
        Memory:6592 kb
    ****************************************************************/
     
    //By BLADEVIL
    type
        rec                     =record
            left, right, root   :longint;
        end;
     
    var
        n, m                    :longint;
        a                       :array[0..10010] of longint;
        t                       :array[0..40010] of rec;
        bt                      :array[0..300000] of longint;
        b_size, b_left, b_right :array[0..300000] of longint;
        b_key                   :array[0..300000] 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 rotate_right(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_right[t]]+b_size[b_left[t]]+1;
        t:=k;
    end;
     
    procedure rotate_left(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_right[t]]+b_size[b_left[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
                rotate_right(b_left[t]) else
            if b_size[b_right[b_left[t]]]>b_size[b_right[t]] then
            begin
                rotate_left(b_left[t]);
                rotate_right(t);
            end else exit;
        end else
        begin
            if b_size[b_right[b_right[t]]]>b_size[b_left[t]] then
                rotate_left(b_right[t]) else
            if b_size[b_left[b_right[t]]]>b_size[b_left[t]] then
            begin
                rotate_right(b_right[t]);
                rotate_left(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_right[t]=0) and (v>b_key[t]) 
            or (b_left[t]=0) and (v<b_key[t]) then
        begin
            delete:=b_key[t];
            if (b_left[t]=0) or (b_right[t]=0) then
                t:=b_right[t]+b_left[t] else
                    b_key[t]:=delete(b_left[t],v+1);
        end else
            if v<b_key[t] then delete:=delete(b_left[t],v) else
                delete:=delete(b_right[t],v);
    end;
     
    function rank(var t:longint; v:longint):longint;
    begin
        if t=0 then exit(0);
        if v<=b_key[t] then rank:=rank(b_left[t],v) else
            rank:=rank(b_right[t],v)+b_size[b_left[t]]+1;
    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;
        mid:=(l+r) div 2;
        build(x*2,l,mid); build(x*2+1,mid+1,r);
    end;
     
    procedure change(x,y,z:longint);
    var
        mid                     :longint;
    begin
        mid:=delete(t[x].root,a[y]);
        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) else change(x*2,y,z);
    end;
     
    function ask(x,l,r,k:longint):longint;
    var
        mid                     :longint;
    begin
        ask:=0;
        if (t[x].left=l) and (t[x].right=r) then
        begin
            ask:=rank(t[x].root,k);
            exit;
        end;
        with t[x] do mid:=(left+right) div 2;
        if mid<l then ask:=ask(x*2+1,l,r,k) else
        if mid>=r then ask:=ask(x*2,l,r,k) else
        ask:=ask(x*2,l,mid,k)+ask(x*2+1,mid+1,r,k);
    end;
     
    function succ(var t:longint;v:longint):longint;
    begin
        if t=0 then exit(-1);
        if b_key[t]<v then succ:=succ(b_right[t],v) else
        begin
            succ:=succ(b_left[t],v);
            if succ=-1 then succ:=b_key[t];
        end;
    end;
     
    function pred(var t:longint;v:longint):longint;
    begin
        if t=0 then exit(-1);
        if b_key[t]>v then pred:=pred(b_left[t],v) else
        begin
            pred:=pred(b_right[t],v);
            if pred=-1 then pred:=b_key[t]; 
        end;
    end;
     
    function ask_succ(x,l,r,y:longint):longint;
    var
        mid                     :longint;
    begin
        if (t[x].left=l) and (t[x].right=r) then
        begin
            ask_succ:=succ(t[x].root,y);
            if ask_succ=-1 then ask_succ:=maxlongint;
            exit;
        end;
        with t[x] do mid:=(left+right) div 2;
        if l>mid then ask_succ:=ask_succ(x*2+1,l,r,y) else
        if r<=mid then ask_succ:=ask_succ(x*2,l,r,y) else
        ask_succ:=min(ask_succ(x*2,l,mid,y),ask_succ(x*2+1,mid+1,r,y));
    end;
     
    function ask_pred(x,l,r,y:longint):longint;
    var
        mid                     :longint;
    begin
        if (t[x].left=l) and (t[x].right=r) then
        begin
            ask_pred:=pred(t[x].root,y);
            exit;
        end;
        with t[x] do mid:=(left+right) div 2;
        if l>mid then ask_pred:=ask_pred(x*2+1,l,r,y) else
        if r<=mid then ask_pred:=ask_pred(x*2,l,r,y) else
        ask_pred:=max(ask_pred(x*2,l,mid,y),ask_pred(x*2+1,mid+1,r,y));
    end;
     
    procedure query(x,y,k:longint);
    var
        l, r, mid               :longint;
        ans                     :longint;
        xx                      :longint;
    begin
        l:=1; r:=1000000000;
        while l<=r do
        begin
            mid:=(l+r) div 2;
            xx:=ask(1,x,y,mid);
            if xx>=k-1 then
            begin
                ans:=mid;
                r:=mid-1;
            end else l:=mid+1;
        end;
        if ask(1,x,y,ans)<>k-1 then
            xx:=ask_pred(1,x,y,ans-1) else
            xx:=ask_succ(1,x,y,ans);
        writeln(xx);
    end;
     
    procedure init;
    var
        i                       :longint;
    begin
        read(n,m);
        for i:=1 to n do read(a[i]);
        readln;
        build(1,1,n);
    end;
     
    procedure main;
    var
        i                       :longint;
        ch                      :char;
        l, r, x                 :longint;
         
    begin
        for i:=1 to m do
        begin
            read(ch);
            if ch='Q' then
            begin
                readln(l,r,x);
                query(l,r,x);
            end else
            begin
                readln(l,x);
                change(1,l,x);
                a[l]:=x;
            end;
        end;
    end;
     
    begin
        init;
        main;
    end.
  • 相关阅读:
    IP的幻觉
    糟糕的一天
    windows下批量生成文件
    基于Bandersnatch搭建本地pypi源
    vmware vsphere 无法启动故障;
    关于Centos7客户端代理配置
    怎样在交换机判断是否出现环路了呢?
    小小的网络故障
    express for LINUX
    ESXI 7.0 ovf 导出;
  • 原文地址:https://www.cnblogs.com/BLADEVIL/p/3455336.html
Copyright © 2020-2023  润新知