LCA 樹狀陣列 樹上RMQ

2021-06-26 07:04:51 字數 1438 閱讀 9747

思路:首先求出樹上dfs序列,並且標記樹上每個節點開始遍歷以及最後回溯遍歷到的時間戳,由於需要修改樹上的某兩個節點之間的權值,如果parent[v] = u, 那麼說明修改之後的v的子樹到當前根的距離都會改變,由於遍歷到v時有開始時間戳以及結束時間戳,那麼處於這個區間所有節點都會影響到,於是我們可以通過陣列陣列來更新某個區間的值,只需令從區間起始點之後的每個值都增加乙個改變量了,令區間中止點之後的每個值都減小乙個改變量,這樣我們就可以得到處於該區間的值的改變量。至於如何求樹上兩個節點的lca,這裡可以使用rmq,o(n * log(n))的預處理,o(1)的查詢複雜度。\

#include #include #include #include #include using namespace std;

const int max_n = (200000 + 10000);

struct edge

edge (int _u, int _v, int _w, int _next) : u(_u), v(_v), w(_w), next(_next) {}

} ee[max_n << 2], edge[max_n << 2];

int ne, head[max_n];

void init()

void insert(int u, int v, int w)

int index, dfs_seq[max_n << 2]; //dfs序列

int first[max_n], end[max_n]; //first陣列表示第一次遍歷到的時間戳,end陣列表示最後回溯時遍歷到的時間戳

int parent[max_n], dep[max_n << 2]; //深度

int n, q, st, cost[max_n];

void dfs(int u, int fa, int d, int c)

end[u] = index;

}int dp[max_n][40]; //dp[i][j]表示從時間戳i開始,長度為(1 << j)的區間中深度最小的點的時間戳

void init_rmq()

}} int rmq_query(int l, int r)

int lca(int x, int y)

int c[max_n << 2];

int lowbit(int x)

void update(int i, int val)

}int getsum(int i)

return sum;

} int main()

index = 0;

dfs(st, st, 0, 0);

init_rmq();

memset(c, 0, sizeof(c));

for (int i = 1; i <= q; ++i) else }}

return 0;

}



LCA 樹狀陣列 樹上RMQ

思路 首先求出樹上dfs序列,並且標記樹上每個節點開始遍歷以及最後回溯遍歷到的時間戳,由於需要修改樹上的某兩個節點之間的權值,如果parent v u,那麼說明修改之後的v的子樹到當前根的距離都會改變,由於遍歷到v時有開始時間戳以及結束時間戳,那麼處於這個區間所有節點都會影響到,於是我們可以通過陣列...

RMQ問題的樹狀陣列解法

樹狀陣列中每個元素覆蓋了不同長度的子區間,類似於稀疏表 st 演算法的思想,每乙個陣列元素儲存了輸入數列a在該區間的最小值下標。注意 這裡樹狀陣列不是用來儲存區間累加值,而是區間的最小值下標。這裡針對預處理階段提供兩個演算法 方法1 參考以下實現 中的方法preprocess 採用類似於累加和中的u...

LCA與RMQ演算法

初始化 init rmq max i j 中存的是重j開始的2 i個資料中的最大值,最小值類似,num中存有陣列的值 for i 1 to n max 0 i num i for i 1 to log n log 2 for j 1 to n 1 2 i max i j max max i 1 j ...