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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

长链剖分 总结 【知识点】

發布時間:2023/12/20 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 长链剖分 总结 【知识点】 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

附上自學博客鏈接
https://www.cnblogs.com/Khada-Jhin/p/9576403.html

概念:

長鏈剖分類似于重鏈剖分,只是選擇鏈的標準:
不是 子樹節點最多的兒子,而是 到葉節點的路徑最大的子節點
(所以說是長鏈)

頂點:一條長鏈上深度最小的點


性質:
對于一個有n個節點的樹,

  • 每一個子節點的最長鏈長度不長于他的祖先節點 (顯然。。)

  • 所有長鏈長度之和等于 n(總結點數)
    證明:
    一個點也算一條長鏈,每一個點在且只在一條長鏈上

  • 從根節點走到任何一個節點,最多 n\sqrt{n}n? 條長鏈(這是個大約數)
    證明:
    把一條長鏈上的點抽象成一個點,(總貢獻為1)
    所以,經過的每一個點都不在同一條長鏈上 ,那么走出的這條鏈長度為 k ,
    有:
    根節點一定有一個子節點,鏈長 ≥k\ge kk
    根節點下一個點一定有一條子節點,鏈長 ≥k?1\ge k-1k?1
    …以此類推
    所以走下去后,沒有走過的點為 ∑1k\sum_1^k1k? 約為 k2/2k^2/2k2/2
    所以k最大大約不過 n\sqrt {n}n?


  • 應用:

    例題傳送門

    詢問一棵樹上任意一個點第k個祖先

    O(n*logn)預處理+ O(1)在線回答

    兩次dfs,兩次都類似重鏈剖分的dfs,只是轉換條件換成了鏈長

    void dfs1(int u){len[u]=1;int v;for(int i=1;(1<<i)<=dep[u];++i){fa[u][i]=fa[fa[u][i-1]][i-1];}for(int i=head[u];i;i=e[i].nxt){v=e[i].v;if(v==fa[u][0])continue;fa[v][0]=u;dep[v]=dep[u]+1;dfs1(v);if(len[v]>mx[u])mx[u]=len[v],son[u]=v;}len[u]+=mx[u]; } void dfs2(int u){int v;aft[top[u]].push_back(u);for(int i=head[u];i;i=e[i].nxt){v=e[i].v;if(v==fa[u][0])continue;top[v]=son[u]==v ? top[u] : v;dfs2(v);} }

    重點是詢問環節,
    維護:

  • 我們對于每一條長鏈的頂端,維護兩個 vector 數組
    pre[i][j]:pre[i][j]:pre[i][j]: 從i開始向上第j個祖先(沒錯,暴力維護。。)
    aft[i][j]:aft[i][j]:aft[i][j]: 從i開始向下長鏈上第j個后代

    注意:
    j≥1j \ge1j1 && j≤len[i]j\le{len[i]}jlen[i]

    每一個頂點只維護所在長鏈長度個
    由于長鏈和等于 n(第二條性質) 所以兩個維護復雜度都是 O(n)

  • 再對 1-n(數字)維護一個 highbit(即二進制位上最靠左的1的位置,可以和lowbit對比理解)
    (這個維護不會超過 O(n*log你) )

    操作:

    對于 詢問 第 x 號節點 的 第 k 個祖先 ,我們把目標祖先設為fa,
    分類討論:
    1.fa和x在一條長鏈上,即 dep[x]?dep[top[x]]≥k{dep[x]-dep[top[x]] } \ge kdep[x]?dep[top[x]]k
    直接用top[x]top[x]top[x]aft 數組即可

    2.fa 和 x不在一條長鏈上,即 dep[x]?dep[top[x]]&lt;k{dep[x]-dep[top[x]] } \lt kdep[x]?dep[top[x]]<k
    這個時候我們跳到x的 向上 2highbit(k)2^{highbit(k)}2highbit(k)個祖先 ,設為 y
    注意,剩下的 k?2highbit(k)&lt;2highbit(k)k-2^{highbit(k)} \lt2^{highbit(k)}k?2highbit(k)<2highbit(k)

    對于 y ,y所在長鏈長度一定≥2highbit(k)\ge2^{highbit(k)}2highbit(k) (根據第一條性質)
    所以pre和aft都可以覆蓋

    對于y所在長鏈的頂端,即top[y]
    如果在 fa上方,就和第一種情況相同
    如果在 fa下方, 就用 top[y] 的 pre 數組 O(1)求即可

    int get(int u,int k){if(k>=dep[u])return 0;if(dep[top[u]]<=dep[u]-k)return aft[top[u]][dep[u]-dep[top[u]]-k];u=fa[u][Log[high[k]]];k-=high[k];if(k>=len[u])return 0;return dep[u]-dep[top[u]]>=k ? aft[top[u]][dep[u]-dep[top[u]]-k] : pre[top[u]][k-(dep[u]-dep[top[u]])]; }

    代碼:

    總的代碼寫的很丑。。這里就不給了,其他的維護自己yy一下都很簡單。。

    總結

    以上是生活随笔為你收集整理的长链剖分 总结 【知识点】的全部內容,希望文章能夠幫你解決所遇到的問題。

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