日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

[学习笔记]树链剖分

發布時間:2025/3/21 编程问答 23 豆豆
生活随笔 收集整理的這篇文章主要介紹了 [学习笔记]树链剖分 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

基本思想

樹鏈剖分一種對樹進行劃分的算法,它先通過輕重邊剖分將樹分為多條鏈,保證每條邊屬于且只屬于一條鏈,然后再通過數據結構來維護每一條鏈。

一些定義

樹鏈:樹上的路徑.

剖分:把路徑分類為重鏈和輕鏈.

重兒子:u的子節點中siz[v]值最大的v.

輕兒子:u的其它子節點.

重邊:點u與其重兒子的連邊.

輕邊:點u與其輕兒子的連邊.

重鏈:由重邊連成的路徑.

輕鏈:輕邊.

性質

  • 如果(u,v)為輕邊,則siz[v]$\times$2<siz[u].
  • 從根到某一點的路徑上輕鏈、重鏈的個數都不大于log$\;$n.
  • 樹剖序其實也可以是dfs序的一種.
  • 實現

    一些變量:

    f[u]表示u的父親.

    siz[u]表示以u為根的子樹的大小.

    dep[u]表示u的深度(根深度為1).

    top[u]表示u所在的鏈的頂端節點.

    son[u]表示與u的重兒子.

    重標號:

    p[u]:重標號后u的編號.

    dfs序:dfs的時候先走重邊.

    這樣可以使得重邊的編號是連續的,方便維護.

    • 用兩遍dfs求出所需的所有變量以及重標號.
    int f[N],p[N],dep[N],siz[N],son[N],top[N]; /*top[u]:u所在的鏈的頂端節點,son[u]:u的重兒子*/ inline void dfs1(int u){int m=0;siz[u]=1;for(int i=g[u];i;i=e[i].nxt)if(!dep[e[i].to]){f[e[i].to]=u;dep[e[i].to]=dep[u]+1;dfs1(e[i].to);siz[u]+=siz[e[i].to];if(siz[e[i].to]>m){son[u]=e[i].to;m=siz[e[i].to];}} } inline void dfs2(int u,int tp){top[u]=tp;p[u]=++cnt;ww[cnt]=w[u];if(son[u]) dfs2(son[u],tp);for(int i=g[u];i;i=e[i].nxt){if(e[i].to!=f[u]&&e[i].to!=son[u])dfs2(e[i].to,e[i].to);} }
    • 訪問修改(u,v):

    類似倍增的走法,每次將深度大的往上移,直到u,v屬于同一條鏈.

    inline int sum(int x,int y){int ret=0,t;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]){t=x;x=y;y=t;}ret+=ask(1,p[top[x]],p[x]);x=f[top[x]];}if(p[x]>p[y]){t=x;x=y;y=t;}ret+=ask(1,p[x],p[y]);return ret; } inline void change(int x,int y,int k){int t;while(top[x]!=top[y]){if(dep[top[x]]<dep[top[y]]){t=x;x=y;y=t;}cover(1,p[top[x]],p[x],k);x=f[top[x]];}if(p[x]>p[y]){t=x;x=y;y=t;}cover(1,p[x],p[y],k); }

    轉載于:https://www.cnblogs.com/AireenYe/p/6219160.html

    《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

    總結

    以上是生活随笔為你收集整理的[学习笔记]树链剖分的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。