洛谷 P3384 模板 輕重鏈剖分(樹鏈剖分)

2022-02-13 12:52:40 字數 2738 閱讀 6301

簡單點說,就是把一棵樹變成多條鏈。

這裡說的是重鏈剖分。

在遍歷一顆樹的時候,我們強制從父親節點走向兒子時,先走所有兒子中以兒子為根的子樹最大的那個兒子。

其他的兒子不管什麼順序都可。

這樣就可以把dfs序作為鏈。

例如上面這棵樹,邊上的藍色數字就是遍歷順序。

說一些定義:

重邊:父親結點和重兒子連成的邊;

輕邊:父親節點和輕兒子連成的邊;

重鏈:由多條重邊連線而成的路徑;

輕鏈:由多條輕邊連線而成的路徑;

在上圖中,黑色邊就是重邊。1-4-9-13-14就是一條重鏈,2-6-11也是一條重鏈,3-7也是一條重鏈。

我們把這些鏈用某種資料結構存起來,例如線段樹,就可以去做一些lca、區間操作了。

我們需要兩個dfs,第乙個處理好以每個節點為根的子樹的大小並求出每乙個節點的重兒子是誰,為下乙個dfs做準備。

第二個根據規定的遍歷順序遍歷這棵樹,並把每個點的是第幾個遍歷的記下來id。

同時還要記錄下遍歷順序對應的節點編號rk; 很顯然,rk[a]=b,id[b]=a;

同時還要記錄下每個節點所在鏈的鏈頂是哪個節點(這是保證效率的關鍵)

樹剖一般不會單獨使用,會和其他的演算法一起,比如說用線段樹存鏈,能快速找到兩個節點的最近公共祖先,從而在這兩個節點的路徑上做一些區間操作。

這個題就是這樣。

1 #include2 #include3 #include4

using

namespace

std;

5const

int maxn=100005;6

intn,m,r,mod,p[maxn],va[maxn],cnt;

7long

long lazy[maxn*4];8

intrk[maxn],id[maxn],dp[maxn],size[maxn],son[maxn],topp[maxn],f[maxn];

9long

long s[maxn*4

];10

struct

nodee[maxn*2

];13

void insert(int u,int

v)19

void dfs1(int fa,int u,int

deep)30}

31void dfs2(int fa,int u,int

top)42}

43void pushdown(int id,int l,int

r) 53

void build(int id,int l,int

r)58

int mid=(l+r)/2

;59 build(id*2

,l,mid);

60 build(id*2+1,mid+1

,r);

61 s[id]=(s[id*2]+s[id*2+1])%mod;62}

63void add(int idd,int l,int r,int x,int y,int

value)

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

pushdown(idd,l,r);

73if(x<=mid) add(idd<<1

,l,mid,x,y,value);

74if(mid1|1,mid+1

,r,x,y,value);

75 s[idd]=s[idd*2]+s[idd*2+1

];76 s[idd]%=mod;77}

78int query(int idd,int l,int r,int x,int

y)82

int mid=(l+r)>>1,ans=0;83

pushdown(idd,l,r);

84if(x<=mid) ans+=query(idd<<1

,l,mid,x,y);

85 ans%=mod;

86if(mid1|1,mid+1

,r,x,y);

87return ans%mod;88}

89int

main()

90100 dfs1(-1,r,1

);101 cnt=0

;102 dfs2(-1

,r,r);

103 build(1,1

,n);

104for(int i=1;i<=m;i++)

115if(dp[x]>dp[y])swap(x,y);

116 add(1,1

,n,id[x],id[y],z);

117}

118if(t==2

)127

if(dp[x]>dp[y])swap(x,y);

128 ans+=query(1,1

,n,id[x],id[y]);

129 cout

130}

131if(t==3

)135

if(t==4

)139

}140

return0;

141 }

洛谷P3384輕重鏈剖分模板題

題目鏈結 p3384 模板 輕重鏈剖分 樹剖模板題。樹剖碼量真大 樹剖主要是把樹形結構處理成鏈式結構,從而可以用諸如線段樹 樹狀陣列的資料結構進行維護。學習樹剖之前得先會線段樹 了解lca以及樹型結構的一些專有名詞 樹鏈剖分專有名詞 講解 1.首先是乙個dfs函式,處理出結點的父親 重兒子 深度 子...

P3384 輕重鏈剖分(樹剖模板)

如題,已知一棵包含 nn 個結點的樹 連通且無環 每個節點上包含乙個數值,需要支援以下操作 操作 11 格式 1 x y z1xyz 表示將樹從 xx 到 yy 結點最短路徑上所有節點的值都加上 zz。操作 22 格式 2 x y2xy 表示求樹從 xx 到 yy 結點最短路徑上所有節點的值之和。操...

P3384 模板 輕重鏈剖分(樹鏈剖分模板)

入口 題目描述 如題,已知一棵包含 nn 個結點的樹 連通且無環 每個節點上包含乙個數值,需要支援以下操作 操作 11 格式 1 x y z1 x y z 表示將樹從 xx 到 yy 結點最短路徑上所有節點的值都加上 zz。操作 22 格式 2 x y2 x y 表示求樹從 xx 到 yy 結點最短...