城市網路 倍增

2022-05-07 21:15:10 字數 1895 閱讀 5655

題目描述

有乙個樹狀的城市網路(即 n個城市由 n−1條道路連線的連通圖),首都為 1號城市,每個城市售賣價值為 ai的珠寶。你是乙個珠寶商,現在安排有 q次行程,每次行程為從 u號城市前往 v號城市(走最短路徑),保證 v在 u前往首都的最短路徑上。在每次行程開始時,你手上有價值為 c的珠寶(每次行程可能不同),並且每經過乙個城市時(包括 u和 v),假如那個城市中售賣的珠寶比你現在手上的每一種珠寶都要優秀(價值更高,即嚴格大於),那麼你就會選擇購入。現在你想要對每一次行程,求出會進行多少次購買事件。 輸入格式第一行,兩個正整數 n,q。第二行,n個正整數ai描述每個城市售賣的珠寶的價值。接下來 n−1行,每行描述一條道路x,y (1≤x,y≤n),表示有一條連線 x和 y的道路。接下來 q 行,每行描述一次行程 u,v,c (1≤u,v≤n)。 輸出格式對於每次行程輸出一行,為所購買次數。

樣例輸入

5 4

3 5 1 2 4

1 21 3

2 43 5

4 2 1

4 2 2

4 2 3

5 1 5

樣例輸出

資料範圍與提示

對於 100%的資料,保證 2≤n≤10^5,1≤q≤10^5, 1≤ai≤10^5, 1≤c≤10^5。

可以發現,一旦開始購買,那麼接下來購買的「行程」就可以確定下來了。

其實這種定式的行走路線完全可以歸屬於每個節點,其實就是說我們可以預處理出每個節點相關的接下來的行走路線。

n2 是不可能的,我們可以模仿樹上倍增求 lca 的做法------運用強大的二進位制操作:倍增。

定義倍增陣列 f 【i

】【j】表示若選擇 i 號節點則接下來第 2 λ j 步到的節點編號。(這裡的步是指有貢獻的 『 步 』 )

具體而言,我們對於每乙個節點預處理出離它最近且權值大於它的祖先,那麼這個祖先節點就是經過當前節點後接下

來會產生貢獻的節點(其他節點就直接跳過了)。

如何得到這個點呢?既然是有關祖先節點的資訊,我們便可以利用已經處理好了的祖先的倍增陣列來求得。也就是利

用倍增陣列來求倍增陣列,且前者是已經處理好了的。

對於詢問,我們先從起點跳到詢問路徑中的有效節點中最後乙個不會產生貢獻的節點(特判從起點開始就產生貢獻的

情況),接下來我們只需要一直沿著倍增陣列往上跳直至跳到終點就可以了。

1 #include2

using

namespace

std;

3int n,m,x,y,z,v[200050];4

int head[200050],nex[400050],ver[400050

],tot;

5int dep[200050],f[200050][20];6

int t[200050],dfn[200050

],cnt,top,ans;

7int tx[200050];8

void add(int x,inty)9

14void dfs(int u,int

fa)15

31void

calc()

3246}47

intmain()

4857 dfs(1,0

);58

while(m--)

5964

return0;

65 }

**

城市網路 樹上倍增

題目鏈結 題意 有乙個樹狀的城市網路 即 n 個城市由 n 1 條道路連線的連通圖 首都為 1 號城市,每個城市售賣價值為 a i 的珠寶。現在安排有 q 次行程,每次行程為從 u 號城市前往 v 號城市 走最短路徑 保證 v 在 u 前往首都的最短路徑上。在每次行程開始時,你手上有價值為 c 的珠...

樹上倍增 城市網路

題解 題目中保證了u到v一定在最短路徑上,所以考慮用樹上倍增的方法。我們fa陣列存的是比當前節點val值嚴格大的最近祖先。然後每次倍增的時候更新答案就可以了。include using namespace std typedef long long ll const int n 2e5 7 int ...

牛客 城市網路 樹上倍增

題意 給一棵 n nn 個點的樹,每個節點代表乙個城市,每個城市賣價值為 a ia i ai 的珠寶,有 q qq 次詢問,每次詢問從 u uu 城市到 v vv 城市,一開始有價值為 c cc 的珠寶,如果當前經過的城市珠寶價值大於已有的所有珠寶的最大價值,就購買。保證 v vv 在 u uu 到...