题意:给一棵树,求节点L,L+1,...R的最近公共祖先

思路:先对树dfs一下,从根1出发,经过每条边时记录一下终点和到达这个点的时间截,令r[u]表示到达u这个节点的最早时间截,t[x]表示在时间截x时到达的节点编号,假设对于两个节点u,v,设r[u]<r[v],则在t[r[u]], t[r[u]+1], ..., t[r[v]]这个序列里面一定包含了u和v的LCA。要找出这个LCA也不难,由于这个序列里面的所有节点只有u和v的LCA这个节点的r值最小,于是可以用RMQ求出这个最小r值,然后再利用t数组就得到了LCA的节点编号。对于多个节点的LCA处理方法类似,只需找到多个节点中的r值的最小和最大值,相当于找到了r[u]和r[v],剩下的就与两个点的LCA一样了。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
#pragma comment(linker, "/STACK:10240000,10240000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>  
#include <vector>
#include <algorithm>
#include <queue>
using namespace std;
 
const int maxn = 3e5 + 7;
 
struct Graph {
    vector<vector<int> > G;
    void clear() { G.clear(); }
    void resize(int n) { G.resize(n + 2); }
    vector<int> & operator [] (int x) { return G[x]; }
    int size() { return G.size(); }
    void add(int u, int v) { G[u].push_back(v); }
};
Graph G;
 
struct ST {
    struct FI {
        int a[21];
        int & operator [] (int x) {
            return a[x];
        }
    };
    vector<FI> dp;
    vector<int> T;
 
    void init(int a[], int n, int (*F)(intint)) {
        dp.clear();
        dp.resize(n);
        for (int i = 0; i < n; i ++) dp[i][0] = a[i];
        for (int j = 1; (1 << j) <= n; j ++) {
            for (int i = 0; i + (1 << j) - 1 < n; i ++) {
                dp[i][j] = F(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]);
            }
        }
        T.clear();
        T.resize(n);
        T[1] = 0;
        for (int i = 2; i <= n; i ++) {
            T[i] = T[i - 1];
            if ((i & (i - 1)) == 0) T[i] ++;
        }
    }
    int query(int L, int R, int (*F)(intint)) {
        int t = T[R - L + 1];
        return F(dp[L][t], dp[R - (1 << t) + 1][t]);
    }
};
int fmin(int a, int b) { return a < b? a : b; }
int fmax(int a, int b) { return a > b? a : b; }
struct LCA {
    int clock, r[maxn], t[2 * maxn], b[2 * maxn];
    bool vis[maxn];
    ST st0, st1, st2;
    void dfs(int rt) {
        r[rt] = clock;
        t[clock ++] = rt;
        vis[rt] = true;
        int sz = G[rt].size();
        for (int i = 0; i < sz; i ++) {
            int u = G[rt][i];
            if (!vis[u]) {
                dfs(u);
                t[clock ++] = rt;
            }
        }
    }
    void work() {
        clock = 0;
        memset(vis, 0, sizeof(vis));
        dfs(1);
        for (int i = 0; i < clock; i ++) b[i] = r[t[i]];
        st0.init(b, clock, fmin);
        st1.init(r + 1, (clock + 1) >> 1, fmax);
        st2.init(r + 1, (clock + 1) >> 1, fmin);
    }
    int lca_all(int L, int R) {
        L --; R --;
        int lp = st2.query(L, R, fmin), rp = st1.query(L, R, fmax);
        return t[st0.query(lp, rp, fmin)];
    }
};
 
LCA lca;
int main() {
#ifndef ONLINE_JUDGE
    freopen("in.txt""r", stdin);
#endif // ONLINE_JUDGE
    int n, m;
    while (cin >> n) {
        G.clear();
        G.resize(n);
        for (int i = 0; i < n - 1; i ++) {
            int u, v;
            scanf("%d%d", &u, &v);
            G.add(u, v);
            G.add(v, u);
        }
        lca.work();
        cin >> m;
        for (int i = 0; i < m; i ++) {
            int L, R;
            scanf("%d%d", &L, &R);
            printf("%d\n", lca.lca_all(L, R));
        }
    }
    return 0;
}

[hdu5266]区间LCA的更多相关文章

  1. HDU 5266 pog loves szh III(区间LCA)

    题目链接 pog loves szh III 题意就是  求一个区间所有点的$LCA$. 我们把$1$到$n$的$DFS$序全部求出来……然后设$i$的$DFS$序为$c[i]$,$pc[i]$为$c ...

  2. HDU5266 LCA 树链剖分LCA 线段树

    HDU5266 LCA Description 给一棵 n 个点的树,Q 个询问 [L,R] : 求点 L , 点 L+1 , 点 L+2 -- 点 R 的 LCA. Input 多组数据. The ...

  3. HDU 6065 RXD, tree and sequence (LCA DP)

    RXD, tree and sequence Time Limit: 6000/3000 MS (Java/Others)    Memory Limit: 524288/524288 K (Java ...

  4. 洛谷 P6071 『MdOI R1』Treequery(LCA+线段树+主席树)

    题目链接 题意:给出一棵树,有边权,\(m\) 次询问,每次给出三个数 \(p,l,r\),求边集 \(\bigcap\limits_{i=l}^rE(p,i)\) 中所有边的权值和. 其中 \(E( ...

  5. HDU 5266 pog loves szh III

    题意:给出一棵树,1为根节点,求一段区间内所有点的最近公共祖先. 解法:用一棵线段树维护区间LCA.LCA是dp做法.dp[i][j]表示点i的第2^j个祖先是谁,转移方程为dp[i][j] = dp ...

  6. 『MdOI R1』Treequery

    我们可以思考怎么做呢. 首先我们需要进行一些分类讨论: 我们先思考一下如果所有关键点都在 \(p\) 的子树内, 那显然是所有关键点的 \(Lca\) 到 \(p\) 距离. 如果所有关键点一些在 \ ...

  7. 区间最深LCA

    求编号在区间[l, r]之间的两两lca的深度最大值. 例题. 解:口胡几种做法.前两种基于莫队,第三种是启发式合并 + 扫描线,第四种是lct + 线段树. ①: 有个结论就是这个答案一定是点集中D ...

  8. 区间节点的lca

    题目hdu5266 分析:多节点的LCA就是dfs序中最大最小两个节点的LCA.所以只要每次维持给出节点的dfs序的最大最小,然后就是两点的LCA 代码: rmq的st+lca的倍增 #include ...

  9. hdu5266 pog loves szh III 【LCA】【倍增】

    Pog and Szh are playing games. Firstly Pog draw a tree on the paper. Here we define 1 as the root of ...

随机推荐

  1. Redis Linux安装+配置

    1.进入指定目录,下载资源(也可本地下载后复制到指定目录) wget http://download.redis.io/releases/redis-5.0.5.tar.gz 2.解压到指定目录 ta ...

  2. CAS原理解析

    CAS底层原理 概念 CAS的全称是Compare-And-Swap,它是CPU并发原语 它的功能是判断内存某个位置的值是否为预期值,如果是则更改为新的值,这个过程是原子的 CAS并发原语体现在Jav ...

  3. git分支,git commit,git流程

    1. git分支命令规范 1. Master 主分支 2. Dev 开发分支 3. Feature 功能分支(例如:feature-x) 4. Release 预发布分支(例如:release-1.2 ...

  4. 6.表单提交,input键盘变搜索,有关自定义属性input操作

    1.键盘变搜索 1.) 在form 上加action="#", 2.)input type=search, 3.)此时会提交到 #,需要再添加一个input display=non ...

  5. Suctf知识记录&&PHP代码审计,无字母数字webshell&&open_basedir绕过&&waf+idna+pythonssrf+nginx

    Checkin .user.ini构成php后门利用,设置auto_prepend_file=01.jpg,自动在文件前包含了01.jpg,利用.user.ini和图片马实现文件包含+图片马的利用. ...

  6. java实现自定义哈希表

    哈希表实现原理 哈希表底层是使用数组实现的,因为数组使用下标查找元素很快.所以实现哈希表的关键就是把某种数据类型通过计算变成数组的下标(这个计算就是hashCode()函数 比如,你怎么把一个字符串转 ...

  7. 使用Reactor响应式编程

    介绍 响应式编程 响应式编程不同于我们熟悉的命令式编程,我们熟悉的命令式编程即代码就是一行接一行的指令,按照它们的顺序一次一条地出现.一个任务被执行,程序就需要等到它执行完了,才能执行下一个任务.每一 ...

  8. Taro 2.2 全面插件化,支持拓展和定制个性化功能

    自 2.2 开始,Taro 引入了插件化机制,允许开发者通过编写插件的方式来为 Taro 拓展更多功能或者为自身业务定制个性化功能,欢迎大家进行尝试,共同讨论~ 当前版本 2.2.1 官方插件 Tar ...

  9. java stream中Collectors的用法

    目录 简介 Collectors.toList() Collectors.toSet() Collectors.toCollection() Collectors.toMap() Collectors ...

  10. SpringCloud之整合Feign

    假设提供者有如下服务接口方法 @RestController @RequestMapping("/person") public class PersonController { ...