洛谷P3384輕重鏈剖分模板題

2021-10-09 19:04:00 字數 3924 閱讀 5785

題目鏈結 p3384 【模板】輕重鏈剖分

樹剖模板題。

樹剖碼量真大(

樹剖主要是把樹形結構處理成鏈式結構,從而可以用諸如線段樹、樹狀陣列的資料結構進行維護。

學習樹剖之前得先會線段樹、了解lca以及樹型結構的一些專有名詞:樹鏈剖分專有名詞**講解

1.首先是乙個dfs函式,處理出結點的父親、重兒子、深度、子樹重量。非常簡單:

void

dfs1

(long

long now,

long

long fa,

long

long dep)

}

2.然後是另乙個dfs函式,用於處理每個結點的dfs序和重鏈。

void

dfs2

(long

long now,

long

long tp)

建線段樹的時候,我們是用每個節點的dfs序作為結點編號的(而不是結點原始編號),因為經過兩邊處理之後,有如下性質:

有了上面兩條性質,我們才能用資料結構進行維護。

下面是**參考資料的一段話

回顧上文的那個題目,修改和查詢操作原理是類似的,以查詢操作為例,其實就是個lca,不過這裡使用了top來進行加速,因為top可以直接跳轉到該重鏈的起始結點,輕鏈沒有起始結點之說,他們的top就是自己。需要注意的是,每次迴圈只能跳一次,並且讓結點深的那個來跳到top的位置,避免兩個一起跳從而擦肩而過。

兩個性質:

如果u ,v

u,vu,

v是一條輕邊,那麼有siz

e[u]

>=2

∗siz

e[v]

size[u]>=2*size[v]

size[u

]>=2

∗siz

e[v]

。這個性質很顯然,輕邊的話說明v

vv是u

uu的輕兒子,又因為有siz

e重

>=s

ize輕

size重》=size輕

size

重》=s

ize輕

,因此有此性質。

從根結點到任意結點的路所經過的輕重鏈的個數必定都小於logn。不會證明,此性質可以證明樹剖的時間複雜度為o(n

logn

logn

)o(nlognlogn)

o(nlog

nlog

n) 。

ac**:

long

long n, m, r, q;

long

long aa[

100010];

struct node

e[200010];

long

long depth[

100010];

long

long top[

100010];

long

long father[

100010];

long

long size[

100010];

long

long dfsrank[

100010];

long

long son[

100010];

long

long ww[

100010];

long

long cnt;

long

long ct =1;

long

long head[

100010];

void

add(

long

long u,

long

long v)

void

dfs1

(long

long now,

long

long fa,

long

long dep)

//處理出結點的父親、重兒子、深度、子樹重量

}void

dfs2

(long

long now,

long

long tp)

//處理出重鏈以及各結點的dfs序

//線段樹模板----------------

struct node2

tr[400010];

void

pushup

(long

long k)

void

build

(long

long k,

long

long l,

long

long r)

long

long mid = l + r >>1;

build

(k *

2, l, mid)

;build

(k *2+

1, mid +

1, r)

;pushup

(k);

}void

pushdown

(long

long k)

}void

change

(long

long k,

long

long l,

long

long r,

long

long w)

pushdown

(k);

long

long mid =

(tr[k]

.l + tr[k]

.r)>>1;

if(r <= mid)

change

(k *

2, l, r, w)

;else

if(l > mid)

change

(k *2+

1, l, r, w)

;else

pushup

(k);

}long

long

query

(long

long k,

long

long l,

long

long r)

//線段樹模板------------

intmain()

dfs1

(r,0,1

);dfs2

(r, r)

;build(1

,1, n)

;for

(long

long i =

1; i <= m; i++

)else

}//直到兩個點在同一條鏈上,修改這兩個點之間的子鏈

if(depth[x]

> depth[y]

)swap

(x, y)

;change(1

, dfsrank[x]

, dfsrank[y]

, z);}

else

if(opt ==2)

else}if

(depth[x]

> depth[y]

)swap

(x, y)

; ans =

(ans +

query(1

, dfsrank[x]

, dfsrank[y]))

% q;

printf

("%lld\n"

, ans);}

else

if(opt ==3)

else

if(opt ==4)

}return0;

}

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

簡單點說,就是把一棵樹變成多條鏈。這裡說的是重鏈剖分。在遍歷一顆樹的時候,我們強制從父親節點走向兒子時,先走所有兒子中以兒子為根的子樹最大的那個兒子。其他的兒子不管什麼順序都可。這樣就可以把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 結點最短...