-
Notifications
You must be signed in to change notification settings - Fork 0
/
lca.cpp
113 lines (109 loc) · 2.05 KB
/
lca.cpp
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
class SegmentTree{
int len;
vll all;
vll seg;
public:
SegmentTree(){}
SegmentTree(vll inp)
{
len = inp.Z;
all = inp;
seg.resize(4*len);
build(1,0,len-1);
}
void build(int id, int l, int r)
{
if (l==r)
{
seg[id] = all[l];
return ;
}
int mid=(l+r)/2;
build(2*id,l,mid);
build(2*id+1,mid+1,r);
seg[id] = min(seg[2*id],seg[2*id+1]);
}
ll query(int id, int l, int r, int sl, int sr)
{
if (r < sl || sr < l)
return 1e18;
if (sl <= l && sr >= r)
return seg[id];
int mid = (l+r)/2;
return min(query(2*id,l,mid,sl,sr),query(2*id+1,mid+1,r,sl,sr));
}
ll query(int l,int r)
{
return query(1,0,len-1,l,r);
}
};
struct LCA{
vector<vi> adj;
int n;
int k;
int root;
vi bij;
vi rbij;
vi path;
vi rnk;
vi in,out;
SegmentTree seg;
LCA(){}
LCA(int n_,int r_)
{
n = n_;
root = r_;
adj.resize(n);
bij.resize(n);
rbij.resize(n);
in.resize(n);
out.resize(n);
rnk.resize(n);
k = 0;
}
void addEdge(int a,int b)
{
adj[a].PB(b);
adj[b].PB(a);
}
void dfs(int x, int par,int rk)
{
bij[x]=k++;
rbij[k-1]=x;
path.PB(bij[x]);
in[x] = path.Z-1;
bool in =false;
rnk[x]=rk;
for(int z:adj[x])
if(z!=par)
{
in=true;
dfs(z,x,rk+1);
path.PB(bij[x]);
out[x] = path.Z-1;
}
if (!in)
{
path.PB(bij[x]);
out[x] = path.Z-1;
}
}
void process()
{
dfs(root,-1,0);
seg = SegmentTree(path);
}
int query(int x,int y)
{
int mn = min(in[x],in[y]);
int mx = max(out[x],out[y]);
trace(mn);
trace(mx);
trace(seg.query(mn,mx));
return rbij[seg.query(mn,mx)];
}
int distance(int x,int y)
{
return rnk[x]+rnk[y]-2*rnk[this->query(x,y)];
}
};