比赛 CSP2023-S模拟赛 评测结果 AAAAAAAAAAAAAAAAAAAA
题目名称 坡伊踹 最终得分 100
用户昵称 usr10086 运行时间 6.336 s
代码语言 C++ 内存使用 93.75 MiB
提交时间 2023-10-17 21:42:57
显示代码纯文本
#include <bits/stdc++.h>

using namespace std;

ifstream fin("poitry.in");
ofstream fout("poitry.out");
#define cin fin
#define cout fout

#define int long long

const int N = 2e5 + 10, LOGN = 19;

struct E
{
    int to, v;
};

vector<E> g[N];
int n, q;
int a[N], dep[N], fa[N][LOGN], apdis[N], andis[N], apd_min[N][LOGN], and_min[N][LOGN], mna[N][LOGN], dis[N];

void bfs(int r)
{
    queue<int> q;
    q.push(r); dep[r] = 1, mna[r][0] = a[r], andis[r] = a[r]-dis[r], apdis[r] = a[r]+dis[r], apd_min[r][0] = apdis[r], and_min[r][0] = andis[r], dis[r] = 0;
    while (!q.empty())
    {
        int k = q.front(); q.pop();
        for (E e : g[k])
        {
            int to = e.to, v = e.v;
            if (dep[to]) continue;
            dep[to] = dep[k]+1, fa[to][0] = k, dis[to] = dis[k] + v;
            apdis[to] = a[to]+dis[to], andis[to] = a[to]-dis[to];
            mna[to][0] = a[to], apd_min[to][0] = apdis[to], and_min[to][0] = andis[to];
            for (int i = 1; i < LOGN; i++)
                fa[to][i] = fa[fa[to][i-1]][i-1], mna[to][i] = min(mna[to][i-1], mna[fa[to][i-1]][i-1]), apd_min[to][i] = min(apd_min[to][i-1], apd_min[fa[to][i-1]][i-1]), and_min[to][i] = min(and_min[to][i-1], and_min[fa[to][i-1]][i-1]);
            q.push(to);
        }
    }
}

int lca(int u, int v)
{
    if (dep[u] < dep[v]) swap(u, v);
    for (int i = LOGN-1; ~i; i--)
        if (dep[fa[u][i]] >= dep[v]) u = fa[u][i];
    if (u == v) return u;
    for (int i = LOGN-1; ~i; i--)
        if (fa[u][i] != fa[v][i]) u = fa[u][i], v = fa[v][i];
    return fa[u][0];
}

int min_and(int x, int k)
{
    int res = LLONG_MAX;
    for (int i = LOGN-1; ~i; i--)
        if ((k >> i) & 1) res = min(res, and_min[x][i]), x = fa[x][i];
    return min(res, andis[x]);
}

signed main()
{
    cin >> n >> q;
    for (int i = 1; i <= n; i++) cin >> a[i];
    for (int i = 1, u, v, w; i < n; i++) cin >> u >> v >> w, g[u].push_back({v, w}), g[v].push_back({u, w});
    bfs(1);
    while (q--)
    {
        int u, v;
        cin >> u >> v;
        int x = u, y = v;
        int ac = lca(u, v);
        int l1 = dep[u] - dep[ac] + 1, l2 = dep[v] - dep[ac], len = l1 + l2;
        {
            int tmp = u, cur = LLONG_MAX, amin = LLONG_MAX;
            for (int i = LOGN-1; ~i; i--)
                if (dep[fa[tmp][i]] >= dep[ac] && min({cur, apd_min[tmp][i], apdis[fa[tmp][i]]}) > dis[u]) amin = min(amin, mna[tmp][i]), cur = min(cur, apd_min[tmp][i]), tmp = fa[tmp][i];
            if (tmp != ac)
            {
                amin = min({amin, a[tmp], max(dis[x] - dis[fa[tmp][0]], a[fa[tmp][0]])});
                cout << amin << '\n';
                continue;
            }
        }
//        cout << x << "***" << y << endl;
        // search 2
        int up = l2, tmp = v;
        for (int i = LOGN-1; ~i; i--)
            if ((1<<i) <= up && min_and(fa[tmp][i], up - (1<<i)) <= dis[u]-2*dis[ac]) tmp = fa[tmp][i], up -= (1<<i);
        int amin = LLONG_MAX, bcon = max(dis[x] + dis[tmp] - 2*dis[ac], a[tmp]);
        for (int i = LOGN-1; ~i; i--)
            if (dep[fa[x][i]] >= dep[ac]) amin = min(amin, mna[x][i]), x = fa[x][i];
        amin = min({ amin, a[ac] });
        if (up) tmp = fa[tmp][0], up--;
        for (int i = LOGN-1; ~i; i--)
            if ((up >> i) & 1) amin = min(amin, mna[tmp][i]), tmp = fa[tmp][i];
        cout << min(amin, bcon) << '\n';
    }
}