bzoj 2151 贪心

  几乎完全类似于1150的思路,直接参考那个就行了。

  http://www.cnblogs.com/BLADEVIL/p/3527193.html

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

    Problem: 2151

    User: BLADEVIL

    Language: Pascal

    Result: Accepted

    Time:3224 ms

    Memory:15092 kb

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

 

//By BLADEVIL

type

    pointer=^rec;

    rec                     =record

        pred, succ          :pointer;

        num, fuck           :longint;

    end;

    shit                    =record

        shit1, shit2        :longint;

    end;

     

var

    n, m                    :longint;

    a                       :array[0..200010] of pointer;

    left, right, size       :array[0..400010] of longint;

    key, adr                :array[0..400010] of longint;

    t, tot                  :longint;

    ans                     :longint;

     

procedure left_rotate(var t:longint);

var

    k                       :longint;

begin

    k:=right[t];

    right[t]:=left[k];

    left[k]:=t;

    size[k]:=size[t];

    size[t]:=size[left[t]]+size[right[t]]+1;

    t:=k;

end;

 

procedure right_rotate(var t:longint);

var

    k                       :longint;

begin

    k:=left[t];

    left[t]:=right[k];

    right[k]:=t;

    size[k]:=size[t];

    size[t]:=size[left[t]]+size[right[t]]+1;

    t:=k;

end;

 

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

begin

    if not flag then

    begin

        if size[left[left[t]]]>size[right[t]] then

            right_rotate(t) else

        if size[right[left[t]]]>size[right[t]] then

        begin

            left_rotate(left[t]);

            right_rotate(t);

        end else exit;

    end else

    begin

        if size[right[right[t]]]>size[left[t]] then

            left_rotate(t) else

        if size[left[right[t]]]>size[left[t]] then

        begin

            right_rotate(right[t]);

            left_rotate(t);

        end else exit;

    end;

    maintain(left[t],false);

    maintain(right[t],true);

    maintain(t,true);

    maintain(t,false);

end;

     

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

begin

    if t=0 then

    begin

        inc(tot);

        t:=tot;

        left[t]:=0;

        right[t]:=0;

        size[t]:=1;

        key[t]:=v;

        adr[t]:=k;

    end else

    begin

        inc(size[t]);

        if v<key[t] then insert(left[t],v,k) else

        if v>key[t] then insert(right[t],v,k) else

        if v=key[t] then

            if k>adr[t] then insert(right[t],v,k) else

                insert(left[t],v,k);

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

    end;

end;

 

function delete(var t:longint;v,k:longint):shit;

var

    damn                    :shit;

begin

    dec(size[t]);

    if (v=key[t]) and (k=adr[t]) or (v>key[t]) and (right[t]=0) or (v<key[t]) and (left[t]=0) then

    begin

        delete.shit1:=key[t];

        delete.shit2:=adr[t];

        if (left[t]=0) or (right[t]=0) then

            t:=left[t]+right[t] else

            begin

                damn:=delete(left[t],v+1,k);

                key[t]:=damn.shit1;

                adr[t]:=damn.shit2;

            end;

    end else

        if v<key[t] then delete:=delete(left[t],v,k) else

        if v>key[t] then delete:=delete(right[t],v,k) else

            if v=key[t] then

                if k>adr[t] then delete:=delete(right[t],v,k) else

                if k<adr[t] then delete:=delete(left[t],v,k);

end;

 

function mini(var t:longint):longint;

begin

    if right[t]=0 then exit(adr[t]) else exit(mini(right[t]));

end;

     

procedure init;

var

    i                       :longint;

    null                    :pointer;

     

begin

    read(n,m);

    if m>n>>1 then

    begin

        writeln('Error!');

        halt;

    end;

    for i:=1 to n do

    begin

        new(null);

        a[i]:=null;

        read(a[i]^.num);

    end;

    for i:=1 to n do

    begin

        if i=1 then a[i]^.pred:=a[n] else a[i]^.pred:=a[i-1];

        if i=n then a[i]^.succ:=a[1] else a[i]^.succ:=a[i+1];

    end;

    for i:=1 to n do a[i]^.fuck:=i;

end;

 

procedure main;

var

    i                       :longint;

    x                       :longint;

begin

    t:=0;

    for i:=1 to n do insert(t,a[i]^.num,i);

    for i:=1 to m do

    begin

        x:=mini(t);

        ans:=ans+a[x]^.num;

        delete(t,a[x]^.num,a[x]^.fuck);

        delete(t,a[x]^.pred^.num,a[x]^.pred^.fuck);

        delete(t,a[x]^.succ^.num,a[x]^.succ^.fuck);

        a[x]^.num:=a[x]^.pred^.num+a[x]^.succ^.num-a[x]^.num;

        insert(t,a[x]^.num,x);

        a[x]^.pred^.pred^.succ:=a[x];

        a[x]^.pred:=a[x]^.pred^.pred;

        a[x]^.succ^.succ^.pred:=a[x];

        a[x]^.succ:=a[x]^.succ^.succ;

    end;

    writeln(ans);

end;

 

begin

    init;

    main;

end.

 

你可能感兴趣的:(ZOJ)