zoukankan      html  css  js  c++  java
  • 【以前的空间】树套树入门总结

    树套树

    名字看上去很高端很酷炫,其实不难,说白了就是树上建树。什么是树上建树?比如一个区间【1,5】,那么建成线段树就有【1,5】【1,3】【4,5】【1,2】【3】【4】【5】【1】【2】这么多个节点,现在我们把这个节点都变成一棵树(平衡树或者线段数),然后把区间内每个点都上入这个平衡树中,比如【1,3】,那么我们就把【1,3】里面三个数都加到一棵平衡树中,这样就可以直接得到【1,3】中每个树的排名(或者一些其他的工作)。

    由于treap各种短各种方便,bit各种短各种方便,线段树各种快各种常数小(对于平衡树来说,而且此时线段树多是权值线段数)。so,蒟蒻至今只写过bit套treap,bit套线段树。

    1、线段数套treap

    建树过程

    procedure maketree(x,l,r:longint);
    
    var
    
      i,mid:longint;
    
    begin
    
      with tree[x] do begin
    
        left:=l;
    
        right:=r;
    
        root:=0;
    
        for i:=l to r do insert(root,num[i]);
    
      end;
    
      if l=r then exit;
    
      mid:=(l+r)>>1;
    
      maketree(x<<1,l,mid);
    
      maketree(x<<1+1,mid+1,r);
    
    end;
    View Code

    用的时候

    function query(x,l,r,y:longint):longint;
    
    var
    
      mid:longint;
    
    begin
    
      with tree[x] do begin
    
        if (l=left) and (r=right) then exit(rank(root,y));
    
        mid:=(left+right)>>1;
    
        if r<=mid then exit(query(x<<1,l,r,y))
    
        else
    
          if l>mid then exit(query(x<<1+1,l,r,y))
    
            else
    
              exit(query(x<<1,l,mid,y)+query(x<<1+1,mid+1,r,y));
    
      end;
    
    end;
    View Code

    然后treap该怎么用怎么用。

    2、bit套treap

     bit中i节点的区间为【i-lowbit(i)+1,i】;

     建树过程:

    fillchar(root[0],sizeof(root[0]),0);
    
      for i:=1 to n do begin
    
        root[i]:=0;
    
        for j:=i-lowbit(i)+1 to i do
    
          insert(root[i],num[j]);
    
      end;
    
    end;
    View Code

    修改和查询

    procedure del(x:longint);
    
    var
    
      old:longint;
    
    begin
    
      old:=x;
    
      x:=hash[x];
    
      while x<=n do begin
    
        delete(root[x],old);
    
        inc(x,lowbit(x));
    
      end;
    
    end;
    
    
    
    function askbig(x,y:longint):longint;
    
    var
    
      ans:longint;
    
    begin
    
      ans:=0;
    
      while x>0 do begin
    
        ans:=ans+getbig(root[x],y);
    
        dec(x,lowbit(x));
    
      end;
    
      exit(ans);
    
    end;
    View Code

    不过就是bst在某些地方有点问题,比如询问【l,r】的区间,可能会出现每个点i加入后【i-lowbit(i)+1,i】不属于【l,r】,所以我们用bit时,除了i点对应的【i-lowbit(i)+1,i】区间外,还要在加一个只包含i这个点的bst。方便以后用吧。

    取区间的方法,sroot保存的是区间的根,然后以后直接for一边就可以访问区间内所以的根了)

    procedure before(l,r:longint);
    
    var
    
      i,k:longint;
    
    begin
    
      sum:=0;
    
      i:=r;
    
      while i>=l do begin
    
        k:=i-lowbit(i)+1;
    
        if k>=l then begin
    
          inc(sum);
    
          sroot[sum]:=root[i];
    
          i:=k-1;
    
        end
    
        else begin
    
          inc(sum);
    
          sroot[sum]:=root2[i];
    
          dec(i);
    
        end;
    
      end;
    
    end;
    View Code

    3、bit套线段树

    这个东西跑起来快,而且写起来比bst短,挺赞的。要注意的就是要见权值线段树。

    建立过程:

    procedure build;
    
    var
    
      i,j,x,mid:longint;
    
    begin
    
      tot:=n;
    
      for i:=1 to n do begin
    
        root[i]:=i;
    
        tree[i].left:=0;
    
        tree[i].right:=mm;
    
        tree[i].lson:=0;
    
        tree[i].rson:=0;
    
      end;
    
      for i:=1 to n do
    
        for j:=i-lowbit(i)+1 to i do begin
    
          x:=root[i];
    
          while true do begin
    
            inc(tree[x].sum);
    
            if tree[x].left=tree[x].right then break;
    
            mid:=(tree[x].left+tree[x].right)>>1;
    
            if num[j]<=mid then begin
    
              if tree[x].lson=0 then addson(tree[x].lson,tree[x].left,mid);
    
              x:=tree[x].lson;
    
            end
    
            else begin
    
              if tree[x].rson=0 then addson(tree[x].rson,mid+1,tree[x].right);
    
              x:=tree[x].rson;
    
            end;
    
          end;
    
        end;
    
    end;
    View Code

    修改过程:(addson,表示加点)

    procedure change(i,new:longint);
    
    var
    
      old,x,mid:longint;
    
    begin
    
      old:=num[i];
    
      num[i]:=new;
    
      while i<=n do begin
    
        x:=root[i];
    
        while true do begin
    
          inc(tree[x].sum);
    
          if tree[x].left=tree[x].right then break;
    
          mid:=(tree[x].left+tree[x].right)>>1;
    
          if new<=mid then begin
    
            if tree[x].lson=0 then addson(tree[x].lson,tree[x].left,mid);
    
            x:=tree[x].lson;
    
          end
    
          else begin
    
            if tree[x].rson=0 then addson(tree[x].rson,mid+1,tree[x].right);
    
            x:=tree[x].rson;
    
          end;
    
        end;
    
        x:=root[i];
    
        while true do begin
    
          dec(tree[x].sum);
    
          if tree[x].left=tree[x].right then break;
    
          mid:=(tree[x].left+tree[x].right)>>1;
    
          if old<=mid then x:=tree[x].lson
    
            else x:=tree[x].rson;
    
        end;
    
        inc(i,lowbit(i));
    
      end;
    
    end;
    View Code

    bz题目:

    1901: Zju2112 Dynamic Rankings

    2453: 维护队列

    2141: 排队

    3295: [Cqoi2011]动态逆序对

  • 相关阅读:
    基于DOM的XSS注入漏洞简单解析
    jQuery DOM XSS漏洞
    亿能测试白盒安全测试模板V1.0发布
    Java代码安全测试解决方案
    关于Java安全的书
    Spring安全资料整理列表
    Find Security Bugs研究,邀请志同道合者一起参与
    IBM发布AppScan Source 8.7:减少iOS企业级应用安全风险
    安全测试电子书大全[持续更新]
    开源安全测试
  • 原文地址:https://www.cnblogs.com/Macaulish/p/6492131.html
Copyright © 2011-2022 走看看