P9487 「LAOI-1」小熊游景点 题解

出题人题解。

x(u,v)uv 路径边权和,y(u,v)uv 路径点权和。

题目中求 x(a,p)+x(b,p)+2x(p,q)=x(a,b)+2x(p,q) 最小的前提下 y(a,p)+y(b,p)+2y(p,q)2sp=y(a,b)+2y(p,q)sp 最大,

x(a,b),y(a,b) 是定值,只需令 x(p,q) 最小的前提下 2y(p,q)sp 最大。

考虑对每个 ab 路径上的 p 维护出 x(p,q) 最小值以及此时 2y(p,q)sp 最大值。

换根 DP 维护之。设 fp,0/1qx 子树内时 x(p,q) 的最小值 / 次小值,则容易得到状态转移方程:

fp,0=min({fq,0+x(p,q)|qsonp}{0})fp,1=secondmin({fq,0+x(p,q)|qsonp}{0})

转移时记录 2y(p,q)sp 最大值。

gp,0/1x(p,q) 的最小值 / 次小值,则 gpfp,gfap 转移而来,gfapffap,gfafap 转移而来,ffap 可能fp 转移而来,存在重复计算。

需要记录 kp 为转移到 gp 的点,从而消除重复计算。

则有状态转移方程:

gp,0=min{fp,0,gfap,[kfap=p]+x(p,fap)}gp,1=secondmin{fp,0,fp,1,gfap,[kfap=p]+x(p,fap)}

转移时记录 2y(p,q)sp 最大值。

则问题转化为求静态树链最小值,用树上倍增维护之。

#include <cstdio>
#include <algorithm>
#define getchar() (p1 == p2 && (p2 = (p1 = buf) + fread(buf, 1, 1 << 21, stdin), p1 == p2) ? EOF : *p1++)
using namespace std;
char buf[1 << 23], *p1 = buf, *p2 = buf, obuf[1 << 23], *O = obuf;
inline int R()
{
    int r = 0;
    bool f = 0;
    char c = getchar();
    while (c < '0' || c > '9')
        f = c == '-', c = getchar();
    while (c >= '0' && c <= '9')
        r = r * 10 + c - '0', c = getchar();
    return f ? -r : r;
}
void P(long long x)
{
    if (x < 0)
        *O++ = '-', x = -x;
    if (x >= 10)
        P(x / 10);
    *O++ = x % 10 + '0';
}
struct S
{
    long long x, y, p;
    S operator+(S b) { return {x + b.x, y + b.y}; }
    bool operator<(S b) const { return x == b.x ? y > b.y : x < b.x; }
} Q, F[300050][2], C[300050][20];
struct E
{
    int v, w, t;
} e[1000050];
int n, m, c, a[300050], d[300050], h[300050], f[300050][20];
long long s[300050];
void A(int u, int v, int w)
{
    e[++c] = {v, w, h[u]};
    h[u] = c;
}
void D1(int u)
{
    for (int i = h[u], v; i; i = e[i].t)
        if (!d[v = e[i].v])
        {
            d[v] = d[u] + 1;
            f[v][0] = u;
            for (int i = 1; f[v][i - 1]; ++i)
                f[v][i] = f[f[v][i - 1]][i - 1];
            s[v] = s[u] + a[v];
            D1(v);
            S X = F[v][0] + S{e[i].w, a[v] << 1};
            X.p = v;
            if (X < F[u][0])
                F[u][1] = F[u][0], F[u][0] = X;
            else if (X < F[u][1])
                F[u][1] = X;
        }
}
void D2(int u, int k)
{
    for (int i = h[u], v; i; i = e[i].t)
        if ((v = e[i].v) != k)
        {
            S X = F[u][F[u][0].p == v] + S{e[i].w, a[u] << 1};
            X.p = u;
            if (X < F[v][0])
                F[v][1] = F[v][0], F[v][0] = X;
            else if (X < F[v][1])
                F[v][1] = X;
            D2(v, u);
        }
}
void D3(int u, int k)
{
    for (int i = h[u], v; i; i = e[i].t)
        if ((v = e[i].v) != k)
        {
            C[v][0] = F[v][0];
            for (int i = 1; f[v][i - 1]; ++i)
                C[v][i] = min(C[v][i - 1], C[f[v][i - 1]][i - 1]);
            D3(v, u);
        }
}
int main()
{
    n = R();
    m = R();
    for (int i = 1; i <= n; ++i)
        a[F[i][0].p = F[i][1].p = i] = R();
    for (int i = 1, u, v, w; i < n; ++i)
        u = R(), v = R(), A(u, v, w = R()), A(v, u, w);
    s[1] = a[1];
    D1(d[1] = 1);
    D2(1, 0);
    for (int i = 1; i <= n; ++i)
        F[i][0].y += a[i], F[i][1].y += a[i];
    C[1][0] = F[1][0];
    D3(1, 0);
    for (int i = 0, x, y, u, v, l, k; i < m; ++i)
    {
        Q = {1000000000000000000ll, 0};
        if (d[u = x = R()] < d[v = y = R()])
            swap(x, y);
        while (d[x] > d[y])
            Q = min(Q, C[x][k = __lg(d[x] - d[y])]), x = f[x][k];
        if (x == y)
            Q = min(Q, C[l = x][0]);
        else
        {
            for (k = __lg(d[x]); k >= 0; --k)
                if (f[x][k] != f[y][k])
                    Q = min({Q, C[x][k], C[y][k]}), x = f[x][k], y = f[y][k];
            Q = min({Q, C[x][0], C[y][0], C[l = f[x][0]][0]});
        }
        P(Q.y + s[u] + s[v] - s[l] - s[f[l][0]]);
        *O++ = '\n';
    }
    fwrite(obuf, O - obuf, 1, stdout);
    return 0;
}
posted @   Jijidawang  阅读(7)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 阿里最新开源QwQ-32B,效果媲美deepseek-r1满血版,部署成本又又又降低了!
· 开源Multi-agent AI智能体框架aevatar.ai,欢迎大家贡献代码
· Manus重磅发布:全球首款通用AI代理技术深度解析与实战指南
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· AI技术革命,工作效率10个最佳AI工具
点击右上角即可分享
微信分享提示