zoukankan      html  css  js  c++  java
  • Heavy Light Decomposition

    Note

    1.DFS1
    mark all the depth
    mark fathers
    mark the heavy/light children
    mark the size of each subtree

    void dfs1(long long pos, long long f, long long depth){
      dep[pos] = depth;
      fat[pos] = f;
      sz[pos] = 1;
      long long maxi = -1;
      for (long long v : adj[pos]){
        if (v == f) continue;
        dfs1(v,pos,depth+1);
        sz[pos]+=sz[v];
        if (maxi<sz[v]) {maxi = sz[v];son[pos] = v;}
      }
    }
    

    2.DFS2
    mark the of the members in the base array
    record the top of each node
    traverse heavy son first then light son
    mark the heavy son along the path
    give the base array a value
    record the id of each node

    void dfs2(long long pos, long long top_pos){
      id[pos] = ++cnt;
      wt[cnt] = num[pos];
      top[pos] = top_pos;
      if (!son[pos]) return;
      dfs2(son[pos],top_pos);
      for (long long v : adj[pos]){
        if (v==fat[pos] || v==son[pos])  continue;
        dfs2(v,v);
      }
    }
    

    3.make_tree
    make segment tree base on the base array

    void make_tree(int way, int l, int r){
      if (l==r) {seg[way] = wt[l]%p;return;}
      int mid = (l+r)/2;
      make_tree(way*2,l,mid);
      make_tree(way*2+1,mid+1,r);
      seg[way] = (seg[way*2]+seg[way*2+1])%p;
    }
    //push function
    void push(int way,int lenn){
        lazy[way*2]+=lazy[way];
        lazy[way*2+1]+=lazy[way];
        seg[way*2]+=lazy[way]*(lenn-(lenn>>1));
        seg[way*2+1]+=lazy[way]*(lenn>>1);
        seg[way*2]%=p;
        seg[way*2+1]%=p;
        lazy[way]=0;
    }
    

    4.query_up
    query base on the segment tree

    int query_up(int way, int l, int r, int qlow, int qhigh){
      push(way,l,r);
      if (qlow<= l && r<=qhigh) return seg[way]%p;
      if (l>qhigh || r<qlow) return 0;
    
      int mid = (l+r)/2;
      return (query_up(way*2,l,mid,qlow,qhigh) + query_up(way*2+1,mid+1,r,qlow,qhigh))%p;
    }
    

    5.query
    1) check if they are on the same chain. if Not, add the distance from a node to the top of the chain, and move up
    2) repeat step 1 until they are on the same chain
    3) query the distance between the nodes based on the base array

    int query(int x, int y){
      int ans = 0;
      while(top[x]!=top[y]){
        if (dep[top[x]]<dep[top[y]]) swap(x,y);
        ans = (ans+query_up(1,1,n,id[top[x]],id[x]))%p;
        x = fat[top[x]];
      }
      if (dep[x]>dep[y]) swap(x,y);
      ans = (ans + query_up(1,1,n,id[x],id[y]))%p;
      return ans;
    }
    

    6.query_son
    query the id[x] plus its size -1 the subtree of a node is consecutive in the base array

    int qSon(int x){
      return query_up(1,1,n,id[x],id[x]+sz[x]-1);
    }
    

    7.update
    update normal segment tree (use id as substitution)

    void update(int way, int l, int r, int qlow, int qhigh, int val){
     push(way,l,r);
     if (qlow<=l && r<=qhigh) {
       lazy[way] += val;
       push(way,l,r);
       return;
     }
     if (l>qhigh || r<qlow) return;
     int mid = (l+r)/2;
     update(way*2,l,mid,qlow,qhigh,val);
     update(way*2+1,mid+1,r,qlow,qhigh,val);
     seg[way] = (seg[way*2]+seg[way*2+1])%p;
    }
    

    8.update chain
    1) check if they are on the same chain. If not, update the chain, and go to the father of the chain head
    2) repeat until they are on the same chain
    3) update the id of the nodes on the segment tree

    void upPath(int x, int y, int val){
      while(top[x]!=top[y]){
        if (dep[top[x]]<dep[top[y]]) swap(x,y);
        update(1,1,n,id[top[x]],id[x],val);
        x = fat[top[x]];
      }
      if (dep[x]>dep[y]) swap(x,y);
      update(1,1,n,id[x],id[y],val);
    }
    

    9.update_son
    update id[x] plus its size -1

    void upSon(int x, int val){
      update(1,1,n,id[x],id[x]+sz[x]-1,val);
    }
    

    optional: LCA
    1) check if the two nodes are on the same chain
    2) if not, find the one with a deeper head, move it up
    3) repeat until they are in the same chain
    3) return the one with higher depth

    int LCA (int x , int y ) {
        int fx = top[x] , fy = top[y] ;
        while(fx!=fy) {
            if(level[fx]< level[fy]) swap(x,y) , swap(fx ,fy) ;
            x = fat[fx] ; fx = top[x];
        }
        if( level[x] > level[y] ) swap(x,y) ;
        return x ;
    }
    

    Note to myself
    Segment tree is able to support different data structure

  • 相关阅读:
    spring-AnnotationConfigApplicationContext源码阅读
    图解http pdf
    paasone的创新(2):separated langsysdemo ecosystem及demo driven debug
    Plan9:一个从0开始考虑分布式,分布appmodel的os设计
    terra++
    qtcling
    terracling:前端metalangsys后端uniform backend免编程binding生成式语言系统设想
    ubuntu touch: deepin pc os和deepin mobile os的天然融合
    windows版gbc:基于enginx的组件服务器系统paas,可用于mixed web与websocket game
    WinPE VirtIO云主机版 支持west263 阿里云aliyun 送精简win2k3镜像
  • 原文地址:https://www.cnblogs.com/DannyXu/p/12372291.html
Copyright © 2011-2022 走看看