zoukankan      html  css  js  c++  java
  • 【HNOI 2002】营业额统计

      我发现这道题被各路神牛广泛地作为数据结构的初级模板练手题……也许是这个题可用的数据结构真的太多,线段树、平衡树、伸展树都可以AC。今天我使用了三种实现方法写这个题,目的就是练手……

      本人弱菜,神牛勿BS……

     题目:http://61.187.179.132:8080/JudgeOnline/showproblem?problem_id=1588

    [HNOI2002]营业额统计

    Time Limit:5000MS  Memory Limit:165536K
    Total Submit:1139 Accepted:309
    Case Time Limit:1000MS

    Description  
      Tiger最近被公司升任为营业部经理,他上任后接受公司交给的第一项任务便是统计并分析公司成立以来的营业情况。
      Tiger拿出了公司的账本,账本上记录了公司成立以来每天的营业额。分析营业情况是一项相当复杂的工作。由于节假日,大减价或者是其他情况的时候,营业额会出现一定的波动,当然一定的波动是能够接受的,但是在某些时候营业额突变得很高或是很低,这就证明公司此时的经营状况出现了问题。经济管理学上定义了一种最小波动值来衡量这种情况:
      该天的最小波动值  当最小波动值越大时,就说明营业情况越不稳定。
      而分析整个公司的从成立到现在营业情况是否稳定,只需要把每一天的最小波动值加起来就可以了。你的任务就是编写一个程序帮助Tiger来计算这一个值。
      第一天的最小波动值为第一天的营业额。

    Input

      第一行为正整数 ,表示该公司从成立一直到现在的天数,接下来的n行每行有一个正整数 ,表示第i天公司的营业额。

    Output

      输出文件仅有一个正整数,即Sigma(每天最小的波动值) 。结果小于2^31 。

    Sample Input

    6
    5
    1
    2
    5
    4
    6	

    Sample Output

    12
    

    Hint

    结果说明:5+|1-5|+|2-1|+|5-5|+|4-5|+|6-5|=5+4+1+0+1+1=12

      首先是比较简单的线段树解法。虽然题目中有明显的插入操作,但是我们可以注意到数据的量是一定的,线段树中数据个数为n,而且初始状态线段树中没有数据。那么我们可以预先开一个1..n的线段树,数据域初始为0,那么每次的插入操作就变成了修改第i个值。每次修改维护一下区间的最大值就可以了。

      (抱歉,线段树的代码不小心被我抹掉了……)

      第二种方法可以使用SBT。

    {
    Tag:营业额统计 HNOI_2002
    Method:Size Balanced Tree
    }
    var key,size,left,right:array[0..40000]of longint;
        i,n,x,ans,total,root:longint;
    
    procedure Left_Rotate(var x:longint);
    var y:longint;
    begin
      y:=right[x];
      right[x]:=left[y];
      left[y]:=x;
      size[y]:=size[x];
      size[x]:=size[left[x]]+size[right[x]]+1;
      x:=y;
    end;
    
    procedure Right_Rotate(var x:longint);
    var y:longint;
    begin
      y:=left[x];
      left[x]:=right[y];
      right[y]:=x;
      size[y]:=size[x];
      size[x]:=size[left[x]]+size[right[x]]+1;
      x:=y;
    end;
    
    procedure maintain(var x:longint;flag:boolean);
    begin
      if flag then
        begin
          if size[left[left[x]]]>size[right[x]] then Right_Rotate(x)
            else if size[right[left[x]]]>size[right[x]] then
              begin
                Left_Rotate(left[x]);Right_Rotate(x);
              end
            else exit
       end
      else
        begin
          if size[right[right[x]]]>size[left[x]] then Left_Rotate(x)
            else if size[left[right[x]]]>size[left[x]] then
              begin
                Right_Rotate(right[x]);Left_Rotate(x);
              end
            else exit;
        end;
      maintain(left[x],true);
      maintain(right[x],true);
      maintain(x,true);
      maintain(x,false);
    end;
    
    procedure insert(var x:longint;data:longint);
    begin
      if x=0 then
        begin
          inc(total);
          x:=total;
          size[x]:=1;
          left[x]:=0;
          right[x]:=0;
          key[x]:=data;
        end
      else
        begin
          inc(size[x]);
          if data<=key[x] then insert(left[x],data)
            else insert(right[x],data);
          maintain(x,data<=key[x]);
        end;
    end;
    
    function find(var x:longint;data:longint):longint;
    begin
      if key[x]=data then exit(data);
      if data<key[x] then
        begin
          if left[x]=0 then find:=key[x] else find:=find(left[x],data)
        end
      else
        begin
          if right[x]=0 then find:=key[x] else find:=find(right[x],data);
        end;
      if abs(find-data)>abs(key[x]-data) then exit(key[x]);
    end;
    
    function min(a,b:longint):longint;
    begin
      if a<b then exit(a);
      exit(b);
    end;
    
    begin
      total:=0;size[0]:=0;root:=0;
      readln(n);
      readln(x);
      insert(root,x);
      inc(ans,x);
      for i:=2 to n do
        begin
          readln(x);
          inc(ans,abs(find(root,x)-x));
          insert(root,x);
        end;
      writeln(ans);
      readln;readln;
    end.
    

      第三种方法:Splay

    {
    Tag:HNOI_2002 营业额统计
    Method:Splay
    }
    program HNOI_2002_Count;
    type rec=record
                   lch,rch,father,data:longint;
         end;
    
    var tree:array[0..80000]of rec;
        n,ans,i,x,root,total,a,b:longint;
    
    function min(a,b:longint):longint;
    begin
      if a<b then exit(a);
      exit(b);
    end;
    
    procedure Left_Rotate(var x:longint);
    var y,fa:longint;
    begin
      y:=tree[x].lch;fa:=tree[x].father;
      if x=tree[fa].lch then tree[fa].lch:=y
        else tree[fa].rch:=y;
      tree[y].father:=fa;
      tree[x].lch:=tree[y].rch;
      tree[tree[y].rch].father:=x;
      tree[y].rch:=x;
      tree[x].father:=y;
      x:=y;
    end;
    
    procedure Right_Rotate(var x:longint);
    var y,fa:longint;
    begin
      y:=tree[x].rch;fa:=tree[x].father;
      if x=tree[fa].lch then tree[fa].lch:=y
        else tree[fa].rch:=y;
      tree[y].father:=fa;
      tree[x].rch:=tree[y].lch;
      tree[tree[y].lch].father:=x;
      tree[y].lch:=x;
      tree[x].father:=y;
      x:=y;
    end;
    
    procedure splay(x:longint);
    var y,z:longint;
    begin
      while tree[x].father<>0 do
        begin
          y:=tree[x].father;
          if tree[y].father=0 then
            begin
              if x=tree[y].lch then Left_Rotate(y)
                else Right_Rotate(y);
            end
          else
            begin
              z:=tree[y].father;
              if y=tree[z].lch then
                begin
                  if x=tree[y].lch then
                    begin
                      Left_Rotate(z);
                      Left_Rotate(z);
                    end
                  else
                    begin
                      Right_Rotate(y);
                      Left_Rotate(z);
                    end;
                  end
              else
                begin
                  if x=tree[y].rch then
                    begin
                      Right_Rotate(z);
                      Right_Rotate(z);
                    end
                  else
                    begin
                      Left_Rotate(y);
                      Right_Rotate(z);
                    end;
                end;
            end;
        end;
      root:=x;
    end;
    
    procedure insert(x,data:longint);
    begin
      while true do
        begin
          if data>tree[x].data then
            begin
              if tree[x].rch=0 then
                begin
                  inc(total);
                  tree[total].data:=data;
                  tree[x].rch:=total;
                  tree[total].father:=x;
                  splay(total);
                  exit;
                end
              else x:=tree[x].rch;
            end
          else
            begin
              if tree[x].lch=0 then
                begin
                  inc(total);
                  tree[total].data:=data;
                  tree[x].lch:=total;
                  tree[total].father:=x;
                  splay(total);
                  exit;
                end
              else x:=tree[x].lch;
            end;
        end;
    end;
    
    function pred(x:longint):longint;
    begin
      if x=0 then exit(maxlongint);
      while tree[x].rch<>0 do x:=tree[x].rch;
      exit(tree[x].data);
    end;
    
    function succ(x:longint):longint;
    begin
      if x=0 then exit(maxlongint);
      while tree[x].lch<>0 do x:=tree[x].lch;
      exit(tree[x].data);
    end;
    
    begin
      readln(n);
      total:=3;root:=1;ans:=0;
      readln(x);
      inc(ans,x);
      tree[1].father:=0;
      tree[1].data:=x;
      tree[1].lch:=2;
      tree[1].rch:=3;
      tree[2].father:=1;
      tree[2].data:=-maxlongint div 2;
      tree[3].father:=1;
      tree[3].data:=maxlongint div 2;
      for i:=2 to n do
        begin
          readln(x);
          insert(root,x);
          a:=pred(tree[root].lch);
          b:=succ(tree[root].rch);
          ans:=ans+min(abs(x-a),abs(x-b));
        end;
      writeln(ans);
      readln;readln;
    end.
    
  • 相关阅读:
    cf1270D——交互,思维
    cf1270E —— 奇偶构造!+ 坐标系分类讨论旋转
    cf1207E——交互,思维
    cf1271D——经典 dp+贪心+图论
    cf1271E——数学找规律,二分套二分
    cf1272E——bfs反边图
    cf1272F——经典升维dp,好题!
    cf1276B——割点+深搜树
    cf1276C——单调性分析,思维
    cf1277D——思维贪心+字符串
  • 原文地址:https://www.cnblogs.com/Delostik/p/1987397.html
Copyright © 2011-2022 走看看