JLOI2014松鼠的新家(树上差分)

Posted blog-fgy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JLOI2014松鼠的新家(树上差分)相关的知识,希望对你有一定的参考价值。

题目链接:https://loj.ac/problem/2236

做法

其实没有什么好说的,这个题就属于那种看起来没什么细节,实际也没有什么细节的题,但是却把我埋了,关于这道题的细节请读者自悟

然后就是树上差分,适用于多次操作一次查询的题

把路径$(u, v)$的边权加$val$的操作:

  • $diff[u] += val$, $diff[v] += val$
  • $diff[lca(u, v)] -= val$, $diff[fa[lca(u, v)]] -= val$

#include <iostream>
#include <cstdio>
#define Re register
using namespace std;
inline int read() {
    int x = 0;
    char ch = getchar();
    while (!isdigit(ch)) ch = getchar();
    while (isdigit(ch)) x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
    return x;
}
const int maxN = 300005;
int N, diff[maxN], ord[maxN], num[maxN];
struct Edge {
    int nxt, to;
} e[maxN << 1];
int cnte = 1, head[maxN];
inline void add_Edge(int i, int j) { e[++cnte].nxt = head[i], e[cnte].to = j, head[i] = cnte; }
int dep[maxN], anc[maxN][21];
void dfslca(int u, int fa) {
    dep[u] = dep[fa] + 1;
    anc[u][0] = fa;
    for (int i = head[u]; i; i = e[i].nxt) {
        if (e[i].to == fa)
            continue;
        dfslca(e[i].to, u);
    }
}
inline int LCA(int x, int y) {
    if (dep[x] < dep[y])
        x ^= y ^= x ^= y;
    for (int i = 18; i >= 0; --i)
        if (dep[anc[x][i]] >= dep[y])
            x = anc[x][i];
    if (x == y)
        return x;
    for (int i = 18; i >= 0; --i)
        if (anc[x][i] != anc[y][i])
            x = anc[x][i], y = anc[y][i];
    return anc[x][0];
}
void dfs(int u, int fa) {
    for (Re int v, i = head[u]; i; i = e[i].nxt) {
        if ((v = e[i].to) == fa)
            continue;
        dfs(v, u);
        diff[u] += diff[v];
    }
}
int main() {
    N = read();
    for (Re int i = 1; i <= N; ++i) ord[i] = read(), num[ord[i]] = i;
    for (Re int i = 1, u, v; i < N; ++i) {
        u = read(), v = read();
        add_Edge(u, v), add_Edge(v, u);
    }
    dfslca(1, 0);
    for (int i = 1; i <= 18; ++i)
        for (int u = 1; u <= N; ++u) anc[u][i] = anc[anc[u][i - 1]][i - 1];
    for (Re int i = 1; i < N; ++i) {
        Re int x = ord[i], y = ord[i + 1];
        Re int lca = LCA(x, y);
        diff[anc[lca][0]] -= 1, diff[lca] -= 1;
        diff[x] += 1, diff[y] += 1;
    }
    dfs(1, 0);
    for (int i = 1; i <= N; ++i) printf("%d
", (num[i] == 1) ? diff[i] : (diff[i] - 1));
    return 0;
}

 

以上是关于JLOI2014松鼠的新家(树上差分)的主要内容,如果未能解决你的问题,请参考以下文章

洛谷lca+树上差分P3258 [JLOI2014]松鼠的新家

[填坑]树上差分 例题:[JLOI2014]松鼠的新家(LCA)

BZOJ 3631 [JLOI2014]松鼠的新家 | 树上差分

[Luogu 3258] JLOI2014 松鼠的新家

JLOI 2014 松鼠的新家

[JLOI2014]松鼠的新家