[hdu5266]区间LCA
题意:给一棵树,求节点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)( int , int )) {
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)( int , int )) {
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;
}
|
转载于:https://www.cnblogs.com/jklongint/p/4572399.html
[hdu5266]区间LCA相关推荐
- HDU5266 LCA 树链剖分LCA 线段树
HDU5266 LCA Description 给一棵 n 个点的树,Q 个询问 [L,R] : 求点 L , 点 L+1 , 点 L+2 -- 点 R 的 LCA. Input 多组数据. The ...
- 北大集训2020游记
Day-2 noip2020 时间久了有点忘了考试过程了... 上来倒序开题,T4稍微想了想会了 O(∑wi)O(\sum w_i)O(∑wi),然后冷静了一下觉得正解就是套个插值.然后一直想T3, ...
- 【hdu5266】pog loves szh III (LCA+线段树)
题意:给一颗树,Q次询问L,L+1,L+2...R的LCA 题目传送门 以LCA为权建线段树,直接查询即可 (我用树剖找LCA) 代码: #include<iostream> #inclu ...
- [2020-11-28 contest]素数(数学),精灵(区间dp),农夫约的假期(结论),观察(树链剖分lca+set)
文章目录 素数 solution code 精灵 solution code 农夫约的假期 solution code 观察 solution solution code 素数 solution 通过 ...
- POJ - 2763 Housewife Wind LCA+dfs序+线段树
q次询问求两个点之间的距离,并且可以随时修改某条边的长度,最短距离可以用lca来求,但是树上维护每一个点到root的距离必须要用dfs序来记录时间戳,在dfs的时候顺便记录每一条边(u,v)对应的v节 ...
- P4216 [SCOI2015]情报传递 LCA+树上主席树 离线操作
题意: 给你一棵n个点的树,初始每个位置没有点权 有m次操作 1 x:让一个点从当前时刻开始,每秒操作点权++ 2 x y c:查询一条链中有多少点的点权大于c 其中每秒操作点权++就是指我每操作一次 ...
- [51nod] 1766树上的最远点对 树的直径 树剖LCA+ST表静态查询
题意: 给你一棵带权树,q次查询,每次给出两个区间,[l1,r1][l2,r2][l_1,r_1] [l_2,r_2][l1,r1][l2,r2]从这两个区间中分别选择两个数字,使得这两个点的 ...
- szu 寒训 day#3 ST表 和 LCA问题 附例题 菜鸡解法
昨天我们讲述了树状数组今天我们来讲ST表(解决静态RMQ (Rang Minmum/Maximum Query)问题的数据结构) 假如说我们暴力去查询区间的最值得话每次操作都是O(n) 如果询问次数跟 ...
- 模板 - LCA最近公共祖先(倍增法、Tarjan、树上差分、LCA优化的次小生成树)
整理的算法模板合集: ACM模板 注意x和y的LCA可以是x或者y本身 一.LCA的在线倍增算法 /*给定一棵包含 n个节点的有根无向树,有 m个询问,每个询问 给出了一对节点的编号 x和 y,询问 ...
最新文章
- linux 下面安装mysql
- 一份关于kaggle特征构建技巧和心得
- 编程之美:编程判断两个链表是否相交
- hadoop2.7.3+spark2.1.0+scala2.12.1环境搭建(3)http://www.cnblogs.com/liugh/p/6624491.html
- Entity Framework Core生成的存储过程在MySQL中需要进行处理及PMC中的常用命令
- Android之如何解决Listview里面的值出现了2次
- list foreach方法_Java集合三兄弟List,Set,Map你分的清楚吗?
- vermgr工作笔记002---SVN查看log时报“svn there has been a problem contacting the server”错误
- 系统相机裁剪比例_从照相到摄影你只差这5个技巧!人像裁剪这4大原则你一定要了解...
- Maria DB windows 安装
- 器件选型基本总则及选型标准
- 在多个浏览器中添加IDM插件
- python应该怎么样自学_Python该如何自学?
- 数据结构与算法Python版-第六周作业
- 如何换IP?换IP最简单的方法在这里!
- Node.js + Web Socket 打造即时聊天程序嗨聊(上)
- 为什么要选择NIUSHOP开源网店系统
- C4D制作lowpoly风格物体
- MySQL需要掌握的技能有哪些?超细长文带你掌握MySQL
- WIN10任务管理器中看不到GPU的使用情况
热门文章
- c linux time微秒_学习linux,看这篇1.5w多字的linux命令详解(6小时讲明白Linux)
- mysql查询每小时数据和上小时数据的差值
- Java开发面试题,Spring面试题整理(1)
- python【数据结构与算法】动态规划模版
- 如何自动校正服务器时间,几个常用校正服务器时间
- 构造函数未定义_构造函数(constructor)和观察者模式,谁略胜一筹呢?
- python123动物重量排序_python基本常识
- async await异步发送请求例子
- 网络推广策略之关于网站首页及内页的标题优化写法
- 网络推广——符合网站现状的优化方案才是最适合进行网络推广的方案