90ptsWAon#6,#7求调

P1600 [NOIP2016 提高组] 天天爱跑步

XiaoYiii @ 2023-11-11 21:15:27

#define _CRT_SECURE_NO_WARNINGS 1
#include<bits/stdc++.h>
using namespace std;
const int N = 3 * 1e6 + 10;
struct edge {
    int v, next;
}e[N];
int h[N], etot = 0, dep[N], up[N][20], r[N], d[N], w[N], LOG;
int n, start[N], ans[N], m;
vector <int> ed[N];
vector <pair <int, int> > v[N];
void add_edge(int u, int v) {
    e[etot].v = v;
    e[etot].next = h[u];
    h[u] = etot++;
}
void dfs(int u, int fa) {
    dep[u] = dep[fa] + 1;
    up[u][0] = fa;
    for (int i = h[u]; i != -1; i = e[i].next) {
        if (e[i].v != fa) {
            dfs(e[i].v, u);                     //递归dfs
        }
    }
}
void init_() {
    for (int k = 1; k <= LOG; k++) {
        for (int i = 1; i <= n; i++) {
            up[i][k] = up[up[i][k - 1]][k - 1]; //初始化up数组,跳k等价于先跳一半再跳一半
            //printf("%d %d %d\n", up[i][k], i, k);
        }
    }
}
int LCA_(int u, int v) {
    if (dep[u] < dep[v]) swap(u, v);
    if (dep[u] != dep[v]) {
        //printf("**\n");
        for (int k = LOG; k >= 0; k--) {
            if (dep[up[u][k]] >= dep[v]) u = up[u][k];      //只要没跳过就一直跳
            if (dep[u] == dep[v]) break;
        }
    }                                           //将查询节点变为同一深度
    if (u == v) return u;                       //特判
    for (int k = LOG; k >= 0; k--) {
        if (up[u][k] != up[v][k]) {         //向上一起跳
            u = up[u][k];
            v = up[v][k];
        }
    }
    return up[u][0];
}
void Solve(int u) {
    int rise = dep[u] + w[u], down = w[u] - dep[u] + n;
    if (rise >= n) rise = 0;
    int pre1 = r[rise], pre2 = d[down];
    for (int i = h[u]; i != -1; i = e[i].next) {
        if (e[i].v != up[u][0]) {
            Solve(e[i].v);
        }
    }
    r[dep[u]] += start[u];
    for (int i = 0; i < ed[u].size(); ++i) {
        d[ed[u][i] - dep[u] + n]++;
    }
    ans[u] += r[rise] - pre1 + d[down] - pre2;
    for (int i = 0; i < v[u].size(); ++i) {
        int temp = v[u][i].first;
        r[dep[temp]]--;
        d[dep[temp] - 2 * dep[u] + n]--;
        if (dep[temp] == dep[u] + w[u]) ans[u]--;
    }
}
int main() {
    memset(h, -1, sizeof(h));
    scanf("%d%d", &n, &m);
    while ((1 << LOG) <= n) {
        LOG++;
    }
    LOG--;
    int x, y, z;
    for (int i = 1; i <= n - 1; i++) {
        scanf("%d%d", &x, &y);
        add_edge(x, y);
        add_edge(y, x);
    }
    dfs(1, 0);
    init_();
    for (int i = 1; i <= n; i++) {
        scanf("%d", &w[i]);
    }
    for (int i = 1; i <= m; i++) {
        scanf("%d%d", &x, &y);
        start[x]++;
        z = LCA_(x, y);
        //printf("%d\n", z);
        ed[y].push_back(dep[x] + dep[y] - 2 * dep[z]);
        v[z].push_back(make_pair(x, y));

    }
    Solve(1);
    for (int i = 1; i <= n; i++) {
        printf("%d ", ans[i]);
    }
    return 0;
}

|