LOJ 6192 城市網路(樹上倍增)

2022-04-28 19:27:09 字數 1508 閱讀 6349

一棵以 $ 1 $ 號節點為根的樹,每個點有乙個權值,有 $ q $ 個詢問,每次從 $ x $ 點開始往某個祖先$ y $ 走,初始有權值 $ c $ ,如果路徑上遇到更大的權值,那麼 $ c $ 改為那個權值,問會修改多少次。資料範圍: $ n\leq 2\times 10^5 $

首先因為本題沒有修改操作,所以可以離線維護。然後我們發現如果我們在 $ x $ 處節點被修改權值,那麼問題從這個節點開始就等效於:從 $ x $ 節點以其本身權值為初始權值向根節點走。然後此題還有另乙個突破口:每乙個節點,若以當前節點權值為初始權值,它向根節點走第乙個會被修改的節點是確定的!這是倍增的標誌!!!

結合上面兩個性質,我們可以想出一種做法:用倍增陣列 $ f[200005][19] $ 維護祖輩裡比他大的節點(第乙個比他大的,第二個,第四個,八個........)。如果我們初始權值為 $ v $ ,那麼我們只要找到第乙個比他大的節點(這個也可以用倍增完成),然後我們在這個節點開始用倍增,因為陣列裡記錄都是比當前節點大的節點,所以我們只需將陣列裡所有深度小於終點的節點數記錄下來即可!

至於預處理,首先我們虛擬乙個根節點的父親,權值無限大。然後更新某個節點處置時,找到父輩裡第乙個比他大的節點,用這個節點更新當前節點即可。具體尋找時:我們要從父親節點出發,因為陣列裡記錄的是比他大的節點,我們只需要看看那個節點的權值是否大於當前節點,小於等於才跳,最後得到的節點的父親即為所求!

#include#include#include#include#include#include#include#include#include#include#include#include#define ll long long

#define db double

#define rg register int

using namespace std;

int n,q;

int top;

int a[400005]; //節點權值

int dp[400005]; //節點深度

int f[300005][19]; //樹上倍增

// f陣列存的是祖輩裡比他大的節點(第乙個比他大的,第二個,第四個,八個........)

struct sub[800005];

int tou[400005]; //鏈式前向星

inline int qr()

inline int get(int x,int v)x=f[x][0]; return x; //小於等於才跳,那麼下乙個就是第乙個比他大的

}inline void dfs(int i,int fa)

inline int ask(int x,int y,int v)return res;

}int main() a[0]=1e9; dfs(1,0); //根節點的父親要賦最大!!!

for(rg i=1;i<=q;++i)

return 0;

}

城市網路 樹上倍增

題目鏈結 題意 有乙個樹狀的城市網路 即 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 到...