洛谷 差分 LCA P1600 天天愛跑步

2021-09-29 15:30:46 字數 3153 閱讀 3612

◇題目傳送門◆

考慮如果直接模擬每個人的路徑複雜度就會達到o(n

m)

o(nm)

o(nm

)級別,這樣做肯定要**。

於是換個方向思考:我們以觀察員的視角來解決這道題。即我們統計每個人對於每個觀察員的貢獻。

對於第i

ii個人的行動,我們可以分成兩部分來看:

記u

uu是s,t

s,ts,

t的最近公共祖先,d(u

)d(u)

d(u)

為節點u

uu的深度。

當當前人是從s

ss走到u

uu的時候:

則我們通過畫圖可以知道:

對於該路徑上任何乙個節點v

vv,當d(s

)=wv

+d(v

)d(s)=w_v+d(v)

d(s)=w

v​+d

(v)時,這個人會對v

vv點上的觀察員做出貢獻。即人從s

ss出發,在w

vw_v

wv​秒時被v

vv節點上的觀察員看到。

當人從u

uu走向t

tt的時候:通過畫圖可以知道:

對於該路徑上的任何乙個節點v

vv,若有d(s

)−2d

(u)=

wv−d

vd(s)-2d(u)=w_v-d_v

d(s)−2

d(u)

=wv​

−dv​

,則這個人會對節點v

vv上的觀察員做出貢獻。

相當於在s

ss處出現了數d(s

)d(s)

d(s)

,在u

uu的父親節點處消失;在u

uu處出現了數d(s

)−2d

(u

)d(s)-2d(u)

d(s)−2

d(u)

,在t

tt處消失。

則問題轉化為在以u

uu為根的子樹中,統計有多少個第一類數等於wu+

d(u)

w_u+d(u)

wu​+d(

u)和第二類數等於wv−

d(v)

w_v-d(v)

wv​−d(

v)。於是做樹上差分:開兩個統計兩類數的出現和消失的位置的vector和計數陣列,一遍dfs

dfsdf

s即可,總時間複雜度為o(m

log⁡n+

n)

o(m\log n+n)

o(mlogn+

n)。似乎我寫的常數有點大。。。

#include

#include

#include

using

namespace std;

const

int maxn =

3e5;

const

int maxlog =19;

int n, m;

int w[maxn +5]

;vector<

int> g[maxn +5]

;void

addedge

(int u,

int v)

int dep[maxn +5]

;int fa[maxn +3]

[maxlog +2]

;void

predfs

(int u,

int pre)

}inline

intlca

(int u,

int v)

int sum1[maxn +5]

, sum2[maxn *2+

5];int ans[maxn +5]

;vector<

int> a1[maxn +5]

, a2[maxn +5]

, b1[maxn +5]

, b2[maxn +5]

;void

dfs(

int u,

int pre)

for(

int i =

0; i <

(int

)a1[u]

.size()

; i++

) sum1[a1[u]

[i]]++;

for(

int i =

0; i <

(int

)a2[u]

.size()

; i++

) sum1[a2[u]

[i]]--;

for(

int i =

0; i <

(int

)b1[u]

.size()

; i++

) sum2[b1[u]

[i]+ n]++;

for(

int i =

0; i <

(int

)b2[u]

.size()

; i++

) sum2[b2[u]

[i]+ n]--;

ans[u]

+= sum1[dep[u]

+ w[u]

]+ sum2[w[u]

- dep[u]

+ n]

;//將這棵子樹差分後的正確答案加回去

}int

main()

predfs(1

,0);

for(

int i =

1; i <= n; i++

)scanf

("%d"

,&w[i]);

for(

int i =

1; i <= m; i++

)dfs(1

,0);

for(

int i =

1; i < n; i++

)printf

("%d "

, ans[i]);

printf

("%d\n"

, ans[n]);

return0;

}

洛谷P1600 天天愛跑步 差分 LCA 桶

題目鏈結 一步一步的來考慮 25 直接 o nm 的暴力 鏈的情況 維護兩個差分陣列,分別表示從左向右和從右向左的貢獻,s i 1 統計每個點的子樹內有多少起點即可 t i 1 同樣還是差分的思想,由於每個點 能對其產生的點的深度是相同的 假設為 x 那麼訪問該點時記錄下 dep x 的數量,將結束...

洛谷 P1600 天天愛跑步

題面就不貼上了 把每個玩家的路徑拆成一條到lca的路徑和從lca到終點的路徑 然後,使用樹上差分統計答案即可 那麼,樹上差分是什麼?差分的具體思想是,當某區間內某元素對答案有貢獻,就在區間起點打乙個 1 標記代表多出了乙個對答案有貢獻的元素,在終點打乙個 1標記代表乙個對答案有貢獻的元素在該位置 結...

洛谷P1600 天天愛跑步

樹上的題有點意思啊 這題我最開始的想法是 固定乙個觀測點i,能觀測到的一定是起點距離 i 為 w i 的點的子集合。問題是這個集合只有一部分的點會經過 i 點,就很煩。於是得換個思路,不放固定乙個跑步的人 x 觀察他對哪些觀察者 i 產生了貢獻。於是我們得到了公式,對於上公升階段的點來說,不妨設 s...