• HNOI2004宠物收养所(平衡树)


    treap!

    var i,n,x,y,ans,a,b,root,tot,ft:longint;
        l,r,s,v,hr:array[0..100000] of longint;
    procedure r_rotate(var x:longint);
     var y:longint;
     begin
     y:=l[x];
     l[x]:=r[y];
     r[y]:=x;
     s[y]:=s[x];
     s[x]:=s[l[x]]+s[r[x]]+1;
     x:=y;
     end;
    procedure l_rotate(var x:longint);
     var y:longint;
     begin
     y:=r[x];
     r[x]:=l[y];
     l[y]:=x;
     s[y]:=s[x];
     s[x]:=s[l[x]]+s[r[x]]+1;
     x:=y;
     end;
    procedure insert(var k,key:longint);
     begin
     if k=0 then
      begin
       inc(tot);
       k:=tot;
       l[k]:=0;
       r[k]:=0;
       s[k]:=1;
       v[k]:=key;
       hr[k]:=random(maxlongint);
       exit;
      end;
     inc(s[k]);
     if key<=v[k] then
      begin
       insert(l[k],key);
       if hr[l[k]]>hr[k] then r_rotate(k);
      end
     else
      begin
       insert(r[k],key);
       if hr[r[k]]>hr[k] then l_rotate(k);
      end;
     end;
    function delete(var k:longint;key:longint):longint;
     begin
     dec(s[k]);
     if (key=v[k]) or ((key<=v[k]) and (l[k]=0)) or ((key>v[k]) and (r[k]=0)) then
      begin
       delete:=v[k];
       if (l[k]=0) or (r[k]=0) then k:=l[k]+r[k]
       else v[k]:=delete(l[k],key+1);
       exit;
      end;
     if key<=v[k] then exit(delete(l[k],key))
     else exit(delete(r[k],key));
     end;
    function pre(var k,key:longint):longint;
     begin
     if k=0 then exit(-1);
     if key<=v[k] then exit(pre(l[k],key))
     else
      begin
      pre:=pre(r[k],key);
      if pre=-1 then pre:=v[k];
      end;
     end;
    function suc(var k,key:longint):longint;
     begin
     if k=0 then exit(-1);
     if key>v[k] then exit(suc(r[k],key))
     else
      begin
      suc:=suc(l[k],key);
      if suc=-1 then suc:=v[k];
      end;
     end;
    procedure main;
     begin
     readln(n);
     ans:=0;tot:=0;root:=0;s[root]:=0;
     for i:=1 to n do
      begin
      readln(x,y);
      if x=ft then insert(root,y)
      else
       if s[root]=0 then
         begin
          ft:=x;
          insert(root,y);
         end
       else
        begin
        a:=pre(root,y);b:=suc(root,y);
        if a=-1 then a:=-maxlongint div 10;
        if b=-1 then b:=-maxlongint div 10;
        if abs(b-y)<abs(y-a) then
         begin
         ans:=(ans+abs(b-y)) mod 1000000;
         b:=delete(root,b);
         end
        else
         begin
         ans:=(ans+abs(y-a)) mod 1000000;
         a:=delete(root,a);
         end;
        end;
      end;
     writeln(ans);
     end;
    begin
     main;
    end.               

    插入操作还有另一种写法:

    procedure maintain(var t:longint;flag:boolean); 
        begin 
          if not flag then 
            if s[l[l[t]]]>s[r[t]] then 
              right_rotate(t) 
            else 
              if s[r[l[t]]]>s[r[t]] then 
                begin 
                  left_rotate(l[t]); 
                  right_rotate(t); 
                end 
              else exit 
          else 
            if s[r[r[t]]]>s[l[t]] then 
              left_rotate(t) 
            else 
              if s[l[r[t]]]>s[l[t]] then 
                begin 
                  right_rotate(r[t]); 
                  left_rotate(t); 
                end 
              else exit; 
          maintain(l[t],false); 
          maintain(r[t],true); 
          maintain(t,true); 
          maintain(t,false); 
        end; 
      procedure insert(var t,v:longint); 
        begin 
          if t=0 then 
            begin 
              inc(tt); 
              t:=tt; 
              s[t]:=1; 
              l[t]:=0; 
              r[t]:=0; 
              key[t]:=v; 
            end 
          else 
            begin 
              inc(s[t]); 
              if v<key[t] then insert(l[t],v) 
              else insert(r[t],v); 
              maintain(t,v>=key[t]); 
            end; 
        end;  

    还需要注意的是,如果题目中明确要求求前驱,即小于它的最大数。那么pre操作的返回值应设为正在查找中的关键值,这样可以使整个操作的返回值不会与原值相同。

    如果题中并没有说明必须不同,例如本题,一个数的前驱可以是这个数,那么pre的返回值应设为-1.

    (update:20140810 这不叫另一种写法。。。这叫SBT。。。当时真无知)

  • 相关阅读:
    Ruby向Java发起挑战,红色风暴来了吗?
    学习语义网的好书
    Joel给计算机系学生们七条免费的建议
    ruby rails: 一个高开发效率的web开发框架
    推荐:《真正的执行》
    每个java程序员都应该看看Jakarta Commons
    上海IT俱乐部论坛开通了!
    重构的三个层次
    一些蔡志忠先生的漫画书!
    pythonchanllenge: 解决迷题,非常有趣的学习python的方式
  • 原文地址:https://www.cnblogs.com/zyfzyf/p/3763132.html
Copyright © 2020-2023  润新知