1. 程式人生 > 其它 >dls的資料結構—倍增,dfs序,尤拉序

dls的資料結構—倍增,dfs序,尤拉序

倍增

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]));
        }
    }
}