• 【以前的空间】几道平衡树


    vijos 1459 车展

    一个空的树.. 依次添加1到n。就能解决左端点为1的所有询问了吧。然后从2开始做一遍啊...n方logn得到全部答案。”神牛的话就是这么吊……看上去没什么信息量但还是水很深……实际上要维护子树内元素和。也就是我程序里面写的change,lsum指左子树中所有点的值得和,rsum指右子树中所有点的值得和,zsum指整个子树中节点的和,也就是lsum+rsum+本节点的值。在计算代价的时候是这样的……假设从i加到j需到的代价为sum,首先找到中间值,就是排名为(j-i)div2+1的点l,然后在sum上加上“这个节点左子树上的点的总和与这个节点的值*左子树节点个数的绝对值”,由于后者要比前者大……所以就是key[l]*s[left[l]]。右子树就是反过来。但是sum的值还不止这些,还需要在递归的时候加上一些值,即如果这个点是左儿子,那sum就要加上他爹和他右兄弟上所有点的值与他爹和他右兄弟上所有点数*这个key[l]的值,就是rsum[t]+key[t]-(s[right[t]]+1)*l,如果是右子树也是一样……这样就没了。最后注意,一定要开int64,因为这个错误,wa了3次……     

    const maxn=4000;
    
    var key,s,left,right,a:array[0..maxn] of longint;
    
        lsum,rsum,zsum:array[0..maxn]of int64;
        tt,i,j,k,l,n,m,t:longint;
        f:array[0..2000,0..2000]of int64;
        sum:int64;
    
    procedure change(t:longint);
    
    begin
    
      lsum[t]:=zsum[left[t]];
      rsum[t]:=zsum[right[t]];
      zsum[t]:=lsum[t]+rsum[t]+key[t];
    
    end;
    
    procedure right_rotate(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;
       change(t);
       change(k);
       t:=k;
    
    end;
    
    procedure left_rotate(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;
       change(t);
       change(k);
       t:=k;
    
    end;
    
    procedure maintain(var t:longint;flag:boolean);
    
    begin
    
    if flag=false then
          if s[left[left[t]]]>s[right[t]] then
             right_rotate(t)
          else
             if s[right[left[t]]]>s[right[t]] then begin
                left_rotate(left[t]);
                right_rotate(t);
             end
             else
                exit   else
          if s[right[right[t]]]>s[left[t]] then
             left_rotate(t)
          else
             if s[left[right[t]]]>s[left[t]] then begin
                right_rotate(right[t]);
                left_rotate(t);
             end
             else
                exit;
       maintain(left[t],false);
       maintain(right[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;
          key[t]:=v;
          s[t]:=1;
          left[t]:=0;
          right[t]:=0;
          lsum[t]:=0;
          rsum[t]:=0;
          zsum[t]:=key[t];
       end
       else begin
          inc(s[t]);
          if v<key[t] then begin
             insert(left[t],v);
             inc(lsum[t],v);
             inc(zsum[t],v);
          end
          else begin
             insert(right[t],v);
             inc(rsum[t],v);
             inc(zsum[t],v);
          end;
          maintain(t,v>=key[t]);
    end;
    
    end;
    
    function select(var t:longint;k:longint):longint;
    
    var
    
      l:longint;
    
    begin
    
    if k=s[left[t]]+1 then begin
          l:=key[t];
          sum:=s[left[t]]*l-lsum[t]+rsum[t]-s[right[t]]*l;
          exit(key[t]);
       end else
       if k<=s[left[t]] then begin
          l:=select(left[t],k);
          sum:=sum+rsum[t]+key[t]-(s[right[t]]+1)*l;
          exit(l)
       end
       else begin
          l:=select(right[t],k-1-s[left[t]]);
         sum:=sum+(s[left[t]]+1)*l-key[t]-lsum[t];
         exit(l);
    end;
    
    end;
    
    
    
    begin
    
    readln(n,m);
    
    for i:=1 to n do
        read(a[i]);
      for i:=1 to n do
        f[i,i]:=0;
      for i:=1 to n-1 do begin
        fillchar(left,sizeof(left),0);
        fillchar(s,sizeof(s),0);
        fillchar(right,sizeof(right),0);
        fillchar(lsum,sizeof(lsum),0);
        fillchar(rsum,sizeof(rsum),0);
        fillchar(zsum,sizeof(zsum),0);
        fillchar(key,sizeof(key),0);   //傻逼又没有必要的初始化,去掉也行啦……
        tt:=0;
        t:=0;
        insert(t,a[i]);
        for j:=i+1 to n do begin
          insert(t,a[j]);
          sum:=0;
          k:=select(t,(j-i)div 2+1);
          f[i,j]:=sum;
        end;
      end;
      sum:=0;
      for i:=1 to m do
        begin
          readln(j,k);
          sum:=sum+f[j,k];
        end;
    writeln(sum);
    
    end.
    View Code

    vijos 1647 不差钱

    var
      ans,tot,i,n,p,t:longint;
      s,left,right,key,value:array[0..101000]of longint;
      a:array[0..1000010]of longint;
      m:int64;
     
    procedureleftrotate(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;
     
    procedurerightrotate(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;
     
    proceduremaintain(var t:longint);
    begin
      if s[left[left[t]]]>s[right[t]] then begin
        rightrotate(t);
        maintain(right[t]);
        maintain(t);
        exit;
      end;
      if s[right[left[t]]]>s[right[t]] then begin
        leftrotate(left[t]);
        rightrotate(t);
        maintain(left[t]);
        maintain(right[t]);
        maintain(t);
        exit;
      end;
      if s[right[right[t]]]>s[left[t]] then begin
        leftrotate(t);
        maintain(left[t]);
        maintain(t);
        exit;
      end;
      if s[left[right[t]]]>s[left[t]] then begin
        rightrotate(right[t]);
        leftrotate(t);
        maintain(left[t]);
        maintain(right[t]);
        maintain(t);
      end;
    end;
     
    procedureinsert(var t:longint;v:longint);
    begin
      if t=0 then begin
        inc(tot);
        t:=tot;
        s[tot]:=1;
        left[tot]:=0;
        right[tot]:=0;
        key[tot]:=v;
        value[ans]:=v;
      end
      else begin
        s[t]:=s[t]+1;
        if v<=key[t] then
          insert(left[t],v)
        elseinsert(right[t],v);
        maintain(t);
      end;
    end;
     
    functionselect(var t:longint;k:longint):longint;
    var
      l:longint;
    begin
      if k=s[left[t]]+1 then
        select:=key[t]
      else begin
        if k<=s[left[t]] then
          select:=select(left[t],k)
        else select:=select(right[t],k-1-s[left[t]]);
      end;
    end;
     
    begin
      readln(m);
      t:=0;
      tot:=0;
      ans:=0;
      fillchar(a,sizeof(a),0);
      read(p);
      while p<>0 do begin
        read(n);
        case p of
          1:begin
            inc(ans);
            insert(t,n);
            inc(a[n]);
            end;
          2:dec(a[value[n]]);
          3:begin
            i:=select(t,ans-n+1);
            if i>m then writeln('Dui bu qi,Mei you.')
            else
              if a[i]>0 then writeln('You. ',i,' Yuan.')
              else writeln('Mei you. Zhe ge ke yi you. Zhe ge zhen mei you!')
          end;
        end;
        read(p);
      end;
    end.
    View Code
  • 相关阅读:
    在wampserver环境下配置多个版本的PHP支持
    Jetbrains全系列完美破解--------亲测可用
    python学习笔记1:元组
    python学习笔记0:列表
    入坑:分享几个优秀的编程博客
    java集合-EnumMap与EnumSet
    java集合-TreeSet
    java集合-TreeMap
    java集合-HashMap(JDK1.8)
    java集合-HashSet
  • 原文地址:https://www.cnblogs.com/Macaulish/p/6492024.html
Copyright © 2020-2023  润新知