hihoCoder 1232 Couple Trees(LCA)

题目链接:hihoCoder 1232 Couple Trees

解题思路

用倍增求出每个节点的LCA值, f[u][i] 表示u节点的第 2i 个父亲节点。然后将其排序,用作二分。每次两个节点向上移动,因为节点编号小的一定层数低,所以可以判断哪一个节点移动。

代码

#include <cstdio>
#include <cstring>
#include <algorithm>

using namespace std;
const int maxn = 1e5 + 5;

int N, M;
int fa[maxn][20], ca[maxn], da[maxn];
int fb[maxn][20], cb[maxn], db[maxn];

void init () {
    da[1] = db[1] = 0;
    fa[1][0] = fb[1][0] = 1;

    for (int i = 2; i <= N; i++) {
        scanf("%d", &fa[i][0]);
        da[i] = da[fa[i][0]] + 1;
    }
    for (int i = 2; i <= N; i++) {
        scanf("%d", &fb[i][0]);
        db[i] = db[fb[i][0]] + 1;
    }

    for (int k = 1; k < 20; k++) {
        for (int i = 1; i <= N; i++) {
            fa[i][k] = fa[fa[i][k-1]][k-1];
            fb[i][k] = fb[fb[i][k-1]][k-1];
        }
    }
    for (int i = 1; i <= N; i++) {
        sort(fa[i], fa[i] + 20);
        ca[i] = unique(fa[i], fa[i] + 20) - fa[i];
        sort(fb[i], fb[i] + 20);
        cb[i] = unique(fb[i], fb[i] + 20) - fb[i];
    }
}

int solve (int u, int v) {
    while (u != v) {
        if (u > v) {
            int t = lower_bound(fa[u], fa[u] + ca[u], v) - fa[u];
            if (t == ca[u]) t--;
            u = fa[u][t];
        } else {
            int t = lower_bound(fb[v], fb[v] + cb[v], u) - fb[v];
            if (t == cb[v]) t--;
            v = fb[v][t];
        }
    }
    return u;
}

int main () {
    while (scanf("%d%d", &N, &M) == 2) {
        init();
        int u, v, k = 0;
        for (int i = 1; i <= M; i++) {
            scanf("%d%d", &u, &v);
            u = (u + k) % N + 1, v = (v + k) % N + 1;
            k = solve(u, v);
            printf("%d %d %d\n", k, da[u]-da[k]+1, db[v]-db[k]+1);
        }
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值