dls的資料結構—倍增,dfs序,尤拉序
阿新 • • 發佈:2022-04-21
倍增
1.求lca
2.log求k級祖先
3.lca:可以記錄路徑上的資訊(沒有修改的) 點上的和邊上的都可以
並且這個資訊需要容易使用倍增的形式進行合併(輕量級資料合併)
// 維護路徑上邊的最小值 #include<bits/stdc++.h> using namespace std; const int N = 2e5+10; int h[N], ne[2 * N], e[2 * N], w[2 * N], idx; int n, q; void add(int a, int b, int c){ w[idx] = c, e[idx] = b, ne[idx] = h[a], h[a] = idx++; } const int LOGN = 20; int depth[N], p[LOGN][N], val[LOGN][N]; void dfs(int u, int fa){ depth[u] = depth[fa] + 1; for(int i = h[u]; i != -1; i = ne[i]){ int j = e[i]; if(j == fa) continue; dfs(j, u); p[0][j] = u; val[0][j] = w[i]; } } void init(){ for(int i = 1; i < LOGN; i ++){ for(int j = 1; j <= n; j ++){ p[i][j] = p[i - 1][p[i - 1][j]]; val[i][j] = min(val[i - 1][j], val[i - 1][p[i - 1][j]]); } } } int query(int u, int v){ int res = 1 << 30; if(depth[u] < depth[v]) swap(u, v); int d = (depth[u] - depth[v]); for(int i = 0; i < LOGN; i ++){ if(d >> i & 1){ res = min(res, val[i][u]); u = p[i][u]; } } if(u == v) return res; for(int i = LOGN - 1; i >= 0; i --){ if(p[i][u] != p[i][v]){ res = min(res, min(val[i][u], val[i][v])); u = p[i][u]; v = p[i][v]; } } res = min(res, min(val[0][v], val[0][u])); return res; } int main(){ scanf("%d %d", &n, &q); memset(h, -1, sizeof h); for(int i = 1; i <= n - 1; i ++){ int a, b, c; scanf("%d %d %d", &a, &b, &c); add(a, b, c); add(b, a, c); } dfs(1, 0); init(); while(q --){ int u, v; scanf("%d %d", &u, &v); printf("%d\n", query(u, v)); } }
DFS序
性質:子樹標號連續
可以把子樹問題轉化成序列的區間問題
// 子樹的點權和(區間和問題),某一個點到根的路徑的權值和(每個子樹加上根節點的值) #include<bits/stdc++.h> using namespace std; const int N = 2e5+10; typedef long long LL; int h[N], ne[2 * N], e[2 * N], w[N], idx; LL tr1[N], tr2[N]; int l[N], r[N], tot; int n, q; void add(int a, int b){ e[idx] = b, ne[idx] = h[a], h[a] = idx++; } void dfs(int u, int fa){ l[u] = ++tot; for(int i = h[u]; i != -1; i = ne[i]){ int j = e[i]; if(j == fa) continue; dfs(j, u); } r[u] = tot; } int lowbit(int x){ return x & -x; } void modify(LL tr[], int u, int x){ for(int i = u; i <= n; i += lowbit(i)) tr[i] += x; } LL sum(LL tr[], int x){ LL res = 0; for(int i = x; i; i -= lowbit(i)) res += tr[i]; return res; } void init(){ for(int i = 1; i <= n; i ++){ modify(tr1, l[i], w[i]); modify(tr2, l[i], w[i]); modify(tr2, r[i] + 1, -w[i]); } } int main(){ scanf("%d %d", &n, &q); memset(h, -1, sizeof h); for(int i = 1; i <= n - 1; i ++){ int a, b; scanf("%d %d", &a, &b); add(a, b); add(b, a); } for(int i = 1; i <= n; i ++) scanf("%d", &w[i]); dfs(1, 0); init(); while(q --){ int type; scanf("%d", &type); if(type == 1){ int x, y; scanf("%d %d", &x, &y); int d = y - w[x]; w[x] = y; modify(tr1, l[x], d); modify(tr2, l[x], d); modify(tr2, r[x] + 1, -d); } else if(type == 2){ int x; scanf("%d", &x); printf("%lld %lld\n", sum(tr1, r[x]) - sum(tr1, l[x] - 1), sum(tr2, l[x])); } } }