洛谷P14989 传送 题解 笛卡尔树+LCA

题目链接:https://www.luogu.com.cn/problem/P14989

解题思路完全来自 elainya_stars 大佬的博客

示例程序:

#include <bits/stdc++.h>
using namespace std;
using ll = long long;
const ll mod = 1e9 + 7;
const int maxn = 5e5 + 5;

int n, Q, a[maxn], ls[maxn], rs[maxn], fa[maxn][19], dep[maxn];

void dfs(int u, int d) {
    dep[u] = d;
    if (ls[u]) {
        fa[ ls[u] ][0] = u;
        dfs(ls[u], d+1);
    }
    if (rs[u]) {
        fa[ rs[u] ][0] = u;
        dfs(rs[u], d+1);
    }
}

int lca(int x, int y) {
    if (dep[x] < dep[y]) swap(x, y);
    for (int i = 18; i >= 0; i--) {
        if (dep[ fa[x][i] ] >= dep[y])
            x = fa[x][i];
    }
    if (x == y) return x;
    for (int i = 18; i >= 0; i--) {
        if (fa[x][i] != fa[y][i]) {
            x = fa[x][i];
            y = fa[y][i];
        }
    }
    return fa[x][0];
}

int main() {
    scanf("%d%d", &n, &Q);
    for (int i = 1; i <= n; i++)
        scanf("%d", a+i);
    stack<int> stk;
    for (int i = 1; i <= n; i++) {
        int last = 0;
        while (!stk.empty() && a[stk.top()] < a[i]) {
            last = stk.top();
            stk.pop();
        }
        if (!stk.empty()) rs[stk.top()] = i;
        ls[i] = last;
        stk.push(i);
    }
    int rt;
    do {
        rt = stk.top();
        stk.pop();
    } while (!stk.empty());
    dfs(rt, 1);
    for (int i = 1; i <= 18; i++)
        for (int u = 1; u <= n; u++)
            fa[u][i] = fa[ fa[u][i-1] ][i-1];
    while (Q--) {
        int k, x, y;
        scanf("%d%d", &k, &x);
        for (int i = 1; i < k; i++) {
            scanf("%d", &y);
            x = lca(x, y);
        }
        printf("%d\n", dep[x]);
    }
    return 0;
}
posted @ 2026-09-03 17:09  quanjun  阅读(9)  评论(0)    收藏  举报