[bzoj 1588] 营业额统计 SBT模板

来源:互联网 发布:知象科技 李凌 编辑:程序博客网 时间:2024/05/16 19:06

  使用SBT维护将要插入的点。1,点已经出现了即用find找到,则什么都没必要做……

                                                      2,点没有比它更小或更大的,单独处理

                                                      3,点有比它小和比它大的,则ans加上取min后得出结果。

   P.S:这题我居然wa了两次……认真看了大神的讨论后发现,一个空行意味着营业额为0!!!题目里哪里可以看出来了!!!

var left,right,key,s:array[0..100000] of longint;    n,tt,t,x,i,m1,m2:longint;    m:int64;  procedure leftrotate(var t:longint);  var k:longint;  begin    k:=right[t];    right[t]:=left[k];    left[k]:=t;    s[k]:=s[t];    s[t]:=s[left[t]]+s[right[t]]+1;    t:=k;  end;  procedure rightrotate(var t:longint);  var k:longint;  begin    k:=left[t];    left[t]:=right[k];    right[k]:=t;    s[k]:=s[t];    s[t]:=s[left[t]]+s[right[t]]+1;    t:=k;  end;  procedure maintain(var t:longint;flag:boolean);  begin    if  not flag then        if s[left[left[t]]]>s[right[t]] then rightrotate(t)          else if s[right[left[t]]]>s[right[t]] then            begin              leftrotate(left[t]);              rightrotate(t);            end          else exit    else if s[right[right[t]]]>s[left[t]] then leftrotate(t)           else if s[left[right[t]]]>s[left[t]] then             begin               rightrotate(right[t]);               leftrotate(t);             end         else exit;    maintain(left[t],false);    maintain(right[t],true);    maintain(t,false);    maintain(t,true);  end;  procedure insert(var t:longint;v:longint);  begin    if t=0 then      begin        inc(tt);        t:=tt;        key[t]:=v;        left[t]:=0;        right[t]:=0;        s[t]:=1;      end    else begin           inc(s[t]);           if v<key[t] then insert(left[t],v)             else insert(right[t],v);           maintain(t,v>=key[t]);         end;  end;  function pred(var t:longint;v:longint):int64;  begin    if t=0 then exit(v);    if v<=key[t] then pred:=pred(left[t],v)      else begin             pred:=pred(right[t],v);             if pred=v then pred:=key[t];           end;  end;  function succ(var t:longint;v:longint):int64;  begin    if t=0 then exit(v);    if key[t]<=v then succ:=succ(right[t],v)      else begin             succ:=succ(left[t],v);             if succ=v then succ:=key[t];           end;  end;  function find(var t:longint;v:longint):boolean;  begin    if t=0 then exit(false);    if v<key[t] then      exit(find(left[t],v))      else exit((key[t]=v) or find(right[t],v));  end;  function min(a,b:longint):longint;  begin    if a<b then exit(a) else exit(b);  end;begin  readln(n);  tt:=0;t:=0;  s[0]:=0;  m:=0;  readln(x);  insert(t,x);  m:=x;  for i:=2 to n do    begin      if eof then x:=0      else readln(x);      if  find(t,x) then continue;      m1:=abs(x-pred(t,x));      m2:=abs(x-succ(t,x));      if  m1=0  then  m:=m+m2          else if  m2=0 then m:=m+m1                            else m:=m+min(m1,m2);       insert(t,x);    end;  writeln(m);end.


0 0