树链剖分模板

vector<int>e[N];
int w[N], dfn[N], subsize[N], fa[N], dep[N], wson[N], top[N];
int tol;
int v[N];
int R[N];
void dfs1(int x, int f) {
    subsize[x] = 1;
    fa[x] = f;
    for (int i = 0; i < e[x].size(); i++) {
        int y = e[x][i];
        if (y == f)continue;
        dep[y] = dep[x] + 1;
        dfs1(y, x);
        subsize[x] += subsize[y];
        if (subsize[y] > subsize[wson[x]])wson[x] = y;
    }
}



void dfs2(int x, int t) {
    dfn[x] = ++tol;
    w[tol] = v[x];
    top[x] = t;
    if (wson[x])dfs2(wson[x], t);
    for (int i = 0; i < e[x].size(); i++) {
        int y = e[x][i];
        if (y == fa[x] || y == wson[x])continue;
        dfs2(y, y);
    }
    R[x] = tol;
}


struct node {
    ll v, lz;
    int l, r;
}t[N * 4];

void pushup(int p) {
    t[p].v = t[p * 2].v + t[p * 2 + 1].v;
}

void pushdown(int p) {
    if (t[p].lz) {
        t[p * 2].v += t[p].lz*(t[p * 2].r - t[p * 2].l + 1);
        t[p * 2].lz += t[p].lz;
        t[p * 2 + 1].v += t[p].lz*(t[p * 2 + 1].r - t[p * 2 + 1].l + 1);
        t[p * 2 + 1].lz += t[p].lz;
        t[p].lz = 0;
    }
}

void build(int l, int r, int p) {
    t[p].l = l;
    t[p].r = r;
    t[p].v = 0;
    t[p].lz = 0;
    if (l == r) {
        t[p].v = w[l];
        return;
    }
    int mid = l + r >> 1;
    build(l, mid, p * 2);
    build(mid + 1, r, p * 2 + 1);
    pushup(p);
}


void update(int L, int R, int v, int p) {
    int l = t[p].l, r = t[p].r;
    if (L <= l && r <= R) {
        t[p].v += v * (r - l + 1);
        t[p].lz += v;
        return;
    }
    int mid = l + r >> 1;
    pushdown(p);
    if (mid >= L)update(L, R, v, p * 2);
    if (mid < R)update(L, R, v, p * 2 + 1);
    pushup(p);
}

ll query(int L, int R, int p) {
    int l = t[p].l, r = t[p].r;
    if (L <= l && r <= R) {
        return t[p].v;
    }
    int mid = l + r >> 1;
    pushdown(p);
    ll sum = 0;
    if (mid >= L)sum = (sum + query(L, R, p * 2)) % mod;
    if (mid < R)sum = (sum + query(L, R, p * 2 + 1)) % mod;
    return sum;
}

struct seg {
    int l, r;
}s[N];
int split(int x, int y) {
    int cnt = 0;
    int fx = top[x], fy = top[y];
    while (fx != fy) {
        if (dep[fx] < dep[fy]) {
            swap(fx, fy);
            swap(x, y);
        }
        s[cnt].l = dfn[fx];
        s[cnt++].r = dfn[x];
        x = fa[fx];
        fx = top[x];
    }
    if (dfn[x] > dfn[y])swap(x, y);
    s[cnt].l = dfn[x], s[cnt++].r = dfn[y];
    return cnt;
}


void init(int root, int n) {
    tol = 0;
    dfs1(root, 0);
    dfs2(root, root);
    build(1, n, 1);
}


void  path_update(int x, int y, int z) {
    int n = split(x, y);
    for (int i = 0; i < n; i++)
        update(s[i].l, s[i].r, z, 1);
}
ll path_query(int x, int y) {
    int n = split(x, y);
    ll ans = 0;
    for (int i = 0; i < n; i++)
        ans = (ans + query(s[i].l, s[i].r, 1)) % mod;
    return ans;
}

void subtree_update(int x, int z) {
    update(dfn[x], R[x], z, 1);
}

ll subtree_query(int x) {
    return query(dfn[x], R[x], 1);
}

int lca(int x, int y) {

    int fx = top[x], fy = top[y];
    while (fx != fy) {
        if (dep[fx] < dep[fy]) {
            swap(fx, fy);
            swap(x, y);
        }
        x = fa[fx];
        fx = top[x];
    }
    if (dep[x] > dep[y])
        return y;
    else
        return x;
}

 

树链剖分模板

上一篇:每天一道题(岛屿类型问题)


下一篇:复杂应用开发测试的 ChatOps 实践