樹鏈剖分 咕咕咕了好久好久的qtree3

2022-04-12 02:44:36 字數 2773 閱讀 1679

顯然qtree系列都是樹鏈剖分辣

發現自己沒有專門整理過樹鏈剖分耶

辣麼就把這篇部落格魔改成樹鏈剖分好辣(貌似除了樹剖也沒什麼好寫的)

廢話了辣麼多終於開始了

一.樹剖怎麼寫鴨

二.樹剖有什麼用鴨

三.qtree3題解

樹剖,顧名思義就是把樹 剖成一條一條的東西,然後把一棵樹搞成乙個序列。

咋剖?對於樹上的每個節點,我們定義它的兒子中,有著最大子樹的兒子就是重兒子(因為它畫出來顯得比較重),然後我們從根節點開始,一直走重兒子,就走出來一條重鏈。那些不在重鏈上的邊怎麼辦呢?我們給他們起個名字,叫輕邊。

處理重兒子

void dfs1(int u,int fa)

}

辣麼我們搞這個重鏈到底有什麼用呢

良(du)心(liu)出題人肯定會搞一些樹上的詢問對不對?樹上的詢問一般都要涉及兩個點之間的路徑對不對?要搞路徑就要找lca對不對?這時候就要用到重鏈和輕邊了。

對於每一條鏈都會有乙個鏈的頂部(一條輕邊自己就是一條鏈),我們可以一條鏈一條鏈的往上跳,也就是每次都跳到當前所在鏈的頂部再往上乙個點(以便找下乙個頂部)。這樣,當再跳一步,兩個點所在鏈的頂部相同時,就說明lca在這條鏈中。

再蒟個栗子

現在我們要求6和8的lca

圖中加粗的點是重兒子

6所處的鏈的頂端是1,8的頂端是10

這裡我們先跳頂端比較深的那個點,也就是跳8

如果跳這一步:

這時候發現2和6的頂端是一樣的,說明6和8的lca肯定在1->2->4->6這條鏈中

那麼2和6中靠近根的點就是lca,在這裡就是2。

查詢**(以求點權之和為例)

int sum(int x,int y)

什麼?線段樹怎麼寫?點這裡qwq至於線段樹維護什麼因題而異,這裡就不多說辣。

樹剖可以對樹進行操作,然後把樹搞成乙個區間,再加上線段樹等資料結構的輔助,從而讓我們的暴力跑的更快(港真樹鏈剖分其實是乙個優化暴力)

經典型別(可能以後會補充):原本序列上的操作被duliu出題人搞到了樹上;給出的圖是一棵樹而且還會神煩的改邊權

[傳送](

!(!(

乙個大小坑:

我們在樹剖的時候建的是雙向邊,所以注意#####陣列要開到2e5!!!!!

鑑於luogu是個神奇的**,不開2e5的邊的評測結果是這樣的:

emmmm當時真的以為是query無限遞迴什麼的然後愣是wa了乙個月沒調出來,某天吃飯的時候突然醒悟邊tm開小了

code:

#include#include#include#include#include#include#define pa pairtypedef long long ll;

using namespace std;

inline int read()

while(ch>='0'&&ch<='9')

return f?-x:x;

}const int inf=21474836;

int fir[300009],dfn[100009],son[100009],par[100009],top[100009];

int n,q,dep[100009],cnt,head[100009],sz[100009];

int tim,idx[100009];

struct eed[300009];

void add(int fr,int to)

void dfs1(int now,int fa)

return ;

}void dfs2(int now,int fa)

// printf("dfn[%d]=%d\n",now,dfn[now]);

}void build(int k,int l,int r)

int mid=(l+r)>>1;

build(k<<1,l,mid);

build(k<<1|1,mid+1,r);

fir[k]=inf;

}void chg(int k,int l,int r,const int &v)

int mid=(l+r)>>1;

if(v<=mid) chg(k<<1,l,mid,v);

else chg(k<<1|1,mid+1,r,v);

fir[k]=min(fir[k<<1],fir[k<<1|1]);

}int query(int k,int l,int r,const int &x,const int &y)

int mid=(l+r)>>1;

int rtn=inf;

if(x<=mid) rtn=min(rtn,query(k<<1,l,mid,x,y));

if(middep[y])swap(x,y);

rtn=min(rtn,query(1,1,n,dfn[x],dfn[y]));

return rtn;

}int main()

{ n=read();q=read();

for(int i=1;i好了在結尾安利一道樹剖模板題

LCA的樹鏈剖分實現

這篇本來是要在 樹鏈剖分小節 中寫的,但是我感覺這只是樹鏈剖分的乙個衍生物,所以另開了一篇,如果對樹鏈剖分部分還不是太了解,請看上面的鏈結。計算樹中兩個節點的最近公共祖先,我們一般有爬山法,tarjan離線演算法,或者是將lca轉換成rmq來解,這裡講一講一種新的求lca的演算法,它是基於樹鏈剖分的...

狐假虎威的樹鏈剖分

運算元據結構 線段樹 結束語 最近在做運輸計畫這道題時,發現要用數鏈剖分,於是就打算學學這個玩意兒。其實之前一直以為這個東西是個很複雜的東西,可能 看起來都很長。但是,學了之後,我才發現,這個東西很好懂,而且 之所以很長,也有乙個原因就是它需要使用乙個強大的資料結構 線段樹。線段樹的 其實並不算少,...

樹鏈剖分的學習理解

前言 本文僅為本人學習樹鏈剖分的理解和總結,有誤之處請大佬指點迷津。也有與其他部落格不同或矛盾之處。樹鏈剖分 顧名思義,將樹結構,剖分成鏈狀結構,然後將一條條的鏈拼接成線性結構,然後就可以通過線段樹 樹狀陣列等維護了。說白了就是在樹上,有些值不好維護,通過樹鏈剖分轉化成乙個序列,而序列就好維護了。樹...