16 pts 求调 玄关
查看原帖
16 pts 求调 玄关
182234
ryanright楼主2024/11/26 19:57

rt link

只过了特殊性质 C,但是手搓了十组左右的数据都没问题,求助万能的谷民,在线等,玄关

#include <cstdio>
#include <vector>
#define inf 0x3f3f3f3f3f3f3f3f
#define int long long
using namespace std;
int c[200005], d[200005], dep[200005], fa[200005][20], st[200005][20], pre[200005];
vector<pair<int, int>> g[200005];
void dfs(int x) {
    for (int i = 1; i < 20; i++)
        fa[x][i] = fa[fa[x][i - 1]][i - 1];
    dep[x] = dep[fa[x][0]] + 1;
    st[x][0] = c[x] - d[x] * 2;
    for (auto i: g[x])
        if (i.first != fa[x][0]) {
            fa[i.first][0] = x;
            d[i.first] = d[x] + i.second;
            dfs(i.first);
            st[x][0] = max(st[x][0], st[i.first][0]);
        }
}
void calc(int x) {
    pre[x] = max(pre[x], pre[fa[x][0]]);
    for (int i = 1; i < 20; i++)
        st[x][i] = max(st[x][i - 1], st[fa[x][i - 1]][i - 1]);
    for (auto i: g[x])
        if (i.first != fa[x][0])
            calc(i.first);
}
int lca(int x, int y) {
    if (dep[x] < dep[y])
        swap(x, y);
    for (int i = dep[x] - dep[y], j = 0; i; i >>= 1, j++)
        if (i & 1)
            x = fa[x][i];
    if (x == y)
        return x;
    for (int i = 19; i >= 0; i--)
        if (fa[x][i] != fa[y][i]) {
            x = fa[x][i];
            y = fa[y][i];
        }
    return fa[x][0];
}
signed main() {
    int n, q;
    scanf("%lld%lld", &n, &q);
    for (int i = 1; i <= n; i++)
        scanf("%lld", &c[i]);
    for (int i = 1; i < n; i++) {
        int u, v, w;
        scanf("%lld%lld%lld", &u, &v, &w);
        g[u].emplace_back(make_pair(v, w));
        g[v].emplace_back(make_pair(u, w));
    }
    pre[0] = -inf;
    for (int i = 0; i < 20; i++)
        st[0][i] = -inf;
    dfs(1);
    for (int i = 1; i <= n; i++) {
        pre[i] = st[i][0] + d[i] * 4;
        st[i][0] += d[i] * 2;
    }
    calc(1);
    while (q--) {
        int x, y, ans = -inf;
        scanf("%lld%lld", &x, &y);
        int u = lca(x, y), ret = c[x] + c[y] - d[x] - d[y];
        for (int i = dep[x] - dep[u], j = 0; i; i >>= 1, j++)
            if (i & 1) {
                ans = max(ans, st[x][j]);
                x = fa[x][j];
            }
        for (int i = dep[y] - dep[u], j = 0; i; i >>= 1, j++)
            if (i & 1) {
                ans = max(ans, st[y][j]);
                y = fa[y][j];
            }
        printf("%lld\n", ret + max(ans + d[u] * 2, pre[u]));
    }
    return 0;
}

还有一个比较玄学的就是改成下面这样直接 0 分,要是有大佬的话能不能解答一下:

void dfs(int x) {
    for (int i = 1; i < 20; i++)
        fa[x][i] = fa[fa[x][i - 1]][i - 1];
    st[x][0] = c[x] - d[x] * 2;
    for (auto i: g[x])
        if (i.first != fa[x][0]) {
            fa[i.first][0] = x;
            d[i.first] = d[x] + i.second;
            dep[i.first] = dep[x] + 1;
            dfs(i.first);
            st[x][0] = max(st[x][0], st[i.first][0]);
        }
}
2024/11/26 19:57
加载中...