HDU5266 pog loves szh III - LCA + ST表

传送门
就是简单的ST表问题+ LCA,用ST表预处理好连续区间的LCA,然后进行查询
注意HDU是多组输入,把相应的值清零即可。
LCA采用倍增法,lg是常数优化。
ST表用模板,维护\([i,i + 2^j - 1]\)这个区间的LCA
时间复杂度为预处理\(O(nlogn)\)
查询\(O(mlogn)\)

#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
using namespace std;
const int N = 3e5 + 5;
int st[N][22];
struct Edge{
    int to, next;
}e[N << 1];
int head[N], tot;
void add(int u, int v){
    e[++tot].to = v;
    e[tot].next = head[u];
    head[u] = tot;
}
int depth[N], fa[N][22], lg[N];
void dfs(int u, int fath) {//初始化fa[u][i]与depth[u]
    fa[u][0] = fath, depth[u] = depth[fath] + 1;
    for(int i = 1; i <= lg[depth[u]]; i++)//定理
        fa[u][i] = fa[fa[u][i - 1]][i - 1];
    for(int i = head[u]; i; i = e[i].next){
        int v = e[i].to;
        if(v != fath)
            dfs(v, u);
    }
}
int LCA(int x, int y) {//求两个点的最近公共祖先
    if(depth[x] < depth[y]) swap(x, y);
    while(depth[x] > depth[y])
        x = fa[x][lg[depth[x] - depth[y]] - 1];//到同一深度
    if(x == y) return x;
    for(int k = lg[depth[x]] - 1; k >= 0; k--)//向上跳,一直到LCA的下一个结点
        if(fa[x][k] != fa[y][k])
            x = fa[x][k], y = fa[y][k];
    return fa[x][0];
}
int Query(int l, int r){
    int k = log2(r - l + 1);
    return LCA(st[l][k], st[r - (1 << k) + 1][k]);
}
int main(){
    int n, m;
    while(~scanf("%d", &n)){
        memset(depth, 0, sizeof(depth));
        memset(head, 0, sizeof(head));
        memset(fa, 0, sizeof(fa));
        tot = 0;
        for(int i = 1; i < n; i++){
            int u, v;
            scanf("%d%d", &u, &v);
            add(u, v); add(v, u);
        }
        for(int i = 1; i <= n; i++){
            st[i][0] = i;
            lg[i] = lg[i - 1] + (1 << lg[i - 1] == i);
        }
        dfs(1, 0);
        for(int j = 1; j <= log2(n / 2) + 1; j++)
            for(int i = 1; i + (1 << j) - 1 <= n; i++)
                st[i][j] = LCA(st[i][j - 1], st[i + (1 << (j - 1))][j - 1]);
        scanf("%d", &m);
        for(int i = 1; i <= m; i++){
            int l, r;
            scanf("%d%d", &l, &r);
            printf("%d\n", Query(l, r));
        }
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Emcikem/p/13197316.html