牛客NC13331 城市網路 樹上倍增

2021-10-16 09:12:38 字數 2217 閱讀 1025

鏈結

題目描述

有乙個樹狀的城市網路(即 n 個城市由 n-1 條道路連線的連通圖),首都為 1 號城市,每個城市售賣價值為 a_i 的珠寶。

你是乙個珠寶商,現在安排有 q 次行程,每次行程為從 u 號城市前往 v 號城市(走最短路徑),保證 v 在 u 前往首都的最短路徑上。 在每次行程開始時,你手上有價值為 c 的珠寶(每次行程可能不同),並且每經過乙個城市時(包括 u 和 v ),假如那個城市中售賣的珠寶比你現在手上的每一種珠寶都要優秀(價值更高,即嚴格大於),那麼你就會選擇購入。

現在你想要對每一次行程,求出會進行多少次購買事件。

輸入描述:

第一行,兩個正整數 n , q (2 ≤ n ≤ 10^5 , 1 ≤ q ≤ 10^5)。

第二行,n 個正整數 a_i (1 ≤ a_i ≤ 10^5) 描述每個城市售賣的珠寶的價值。

接下來 n-1 行,每行描述一條道路 x , y (1 ≤ x,y ≤ n),表示有一條連線 x 和 y 的道路。

接下來 q 行,每行描述一次行程 u , v , c (1 ≤ u,v ≤ n , 1 ≤ c ≤ 10^5)。

輸出描述:

對於每次行程輸出一行,為所購買次數。

示例1輸入

5 43 5 1 2 4

1 21 3

2 43 5

4 2 1

4 2 2

4 2 3

5 1 5輸出2

110思路 :

考慮用f[i][j]表示從i往上走,能買珠寶的第 2^j個點是哪個,顯然,如果我們知道每個 f[i][0]的值, 那麼f[i][j]=f[f[i][j−1]][j−1] ( i 往上的第2 ^j−1 個點再往上 2^j−1個點)。那麼 f[i][0]怎麼求呢?肯定不能暴力,因為暴力最壞情況可能會讓你每次都跑到根(構造一條鏈,從根到葉子價值遞增)。這個其實也可也倍增著跳——如果 i 的父親fa比i 大那自不必說,當i的父親fa比i 小,那麼我們可以看fa的父親向上走 2^k(k從大到小列舉)個能買進的點的權值(即 f[fa][k]),如果這個點許可權比 i 點權值小,說明還需要往上走,就跳到f[fa] [k]上並把跳躍的長度減少一半(如果還是剛剛的跳躍高度,從f[fa] [k]往上跳 2 ^k

長度,實際上就是從fa跳 2^k+1 ,相當於就是跳到 f[fa][k+1]了);如果 f[fa][k]這個點的權值比 i 大,說明跳多了,就只是把跳躍長度減少一半再看。

注意我這裡說的跳躍長度都是按照能買東西的點的個數計數,相當於我的f陣列其實是對原樹進行了重建,每個點往上走1步都的連向的它能到的第乙個比他大的點(這樣理解也許會容易很多——即我們對原樹進行變形,每個點都連向它上方第乙個能買東西的點,構成乙個新的森林,於是問題就變成了,從u走到自己上方深度不小於dep[v]的點需要經過多少個點)。

有了這個值之後我們要求從 u 往上走到 v 經過了多少點,也可也倍增去求了——即從 u 出發嘗試往上跳 2^k高度,如果已經跳過 v 了,就減小 k,如果沒有跳到 v 的上方,就先跳上去再減小 k。 注意,因為f陣列存的能買東西的點,很有可能v根本不在這裡面,所有跳的時候是通過判斷深度來判斷是否結束的。

這道題孩子想了好久好久 最終還是參考清楚姐姐的思路才想明白 /(ㄒoㄒ)/~~

** :

#include

using

namespace std ;

const

int maxn =

2e5+10;

typedef

long

long ll ;

vector<

int> v[maxn]

;int a[maxn]

, f[maxn][20

], dep[maxn]

, to[maxn]

;void

dfs(

int p ,

int fa)

}int n , q ;

intmain()

for(

int i = n +

1; i <= n + q ; i++

)dfs(1

,0);

for(

int i =

1; i <= q ; i++)}

cout << ans << endl ;

}return0;

}

牛客網 NC207427 直線 高精度

2.解讀 3.time limit c c 1秒,其他語言2秒 memory limit c c 262144k,其他語言524288k 平面上存在 n nn 條直線。請問 n nn 條直線在平面上最多存在多少交點。輸入資料的第一行是t,表示資料的組數 t 100 t 100 t 10 0 接下來每...

城市漫遊 牛客

題解 u v這條簡單路徑上的邊會經過奇數次,其餘的邊會經過偶數次,因為從簡單路徑中的點出去後還得回來。直接算的話每次詢問都得搜整棵樹,顯然效率是極其低的。如果先預處理出整棵樹的邊都經過偶數次的花費v,那麼答案就等於 v 簡單路徑中的邊經過偶數次的花費 簡單路徑中的邊經過奇數次的代價。下一步是得到後兩...

牛客NC18200烟花

總時間限制 1000ms 記憶體限制 262144k 小a有n個烟花,每個烟花代表著互不相同的顏色,對於第i個烟花,它有pi的概率點燃,現在小a要去點燃它們,他想知道產生顏色的期望個數及產生恰好產生k種顏色的概率 第一行兩個整數n,k.接下來一行n個數,第i個數pi表示第i個烟花被點燃的概率 輸出有...