「LCA」课件配套资料
课件
链接:https://pan.baidu.com/s/1ch2lNQOl3oQCu-HaTPIDJg
提取码:koko
复制这段内容后打开百度网盘手机App,操作更方便哦
代码片段
复杂度分析
\[\log_2 4 = 2
\]
\[2^2 = 4
\]
\[2^{\log_2 4} = 4
\]
\[a^{\log_a c} = c
\]
\[\lg =\log_{10}
\]
\[e=2.741\cdots
\]
\[\ln = \log_e
\]
//
/*
By:Luckyblock
*/
#include <cstdio>
#include <ctype.h>
#include <cstring>
#include <algorithm>
#define LL long long
const int kMaxn = 2e5 + 10;
//=============================================================
int n;
//=============================================================
inline int read() {
int f = 1, w = 0; char ch = getchar();
for (; !isdigit(ch); ch = getchar()) if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
return f * w;
}
namespace Seg {
#define ls (now_<<1)
#define rs (now_<<1|1)
#define mid ((L_+R_)>>1)
LL sum[kMaxn << 2], tag[kMaxn];
void Build(int now_, int L_, int R_) {
if (L_ == R_) return ;
Build(ls, L_, mid);
Build(rs, mid + 1, R_);
}
void Pushup(int now_) {
sum[now_] = (sum[ls] + sum[rs]);
}
void Pushdown(int now_, int L_, int R_) {
sum[ls] += (mid - L_ + 1) * tag[now_];
sum[rs] += (R_ - mid) * tag[now_];
tag[ls] += tag[now_];
tag[rs] += tag[now_];
tag[now_] = 0;
}
void Modify(int now_, int L_, int R_, int l_, int r_, int val_) {
if (l_ <= L_ && R_ <= r_) {
sum[now_] += val_;
tag[now_] += val_;
return ;
}
Pushdown(now_, L_, R_);
if (l_ <= mid) Modify(ls, L_, mid, l_, r_, val_);
if (r_ > mid) Modify(rs, mid + 1, R_, l_, r_, val_);
Pushup(now_);
}
LL Merge(LL L_, LL R_) {
return L_ + R_;
}
LL Query(int now_, int L_, int R_, int l_, int r_) {
if (l_ <= L_ && R_ <= r_) return sum[now_];
Pushdown(now_, L_, R_);
if (l_ > mid) return Query(rs, mid + 1, R_, l_, r_);
if (r_ <= mid) return Query(ls, L_, mid, l_, r_);
return Merge(Query(ls, L_, mid, l_, mid), Query(rs, mid + 1, R_, mid + 1, r_));
// LL ret = 0;
// if (l_ <= mid) ret += Query(ls, L_, mid, l_, r_);
// if (r_ > mid) ret +=(rs, mid + 1, R_, l_, r_);
// return ret;
}
#undef ls
#undef rs
#undef mid
}
//=============================================================
int main() {
int a = 0;
for (int i = 1; i <= n; ++ i) {
a ++;
}
for (int i = 1; i <= n; ++ i) { //i -> n
for (int j = 1; j <= n; j += i) { //S(n n/2 n/3 ... 1) = n ln n < n log n
a ++;
}
}
return 0;
}
倍增
//
/*
By:Luckyblock
*/
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstring>
#define ll long long
const int kMaxn = 5e5 + 10;
const int kMaxm = (kMaxn << 1);
//=============================================================
int n, m, root;
int e_num, head[kMaxn], v[kMaxn << 1], w[kMaxn << 1], ne[kMaxn << 1];
int dep[kMaxn], fa[kMaxn][25], sum[kMaxn][25];
int a[kMaxn], b[kMaxn], lca[kMaxn], val[kMaxn];
//=============================================================
inline int read() {
int f = 1, w = 0;
char ch = getchar();
for (; !isdigit(ch); ch = getchar())
if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
return f * w;
}
void Chkmax(int &fir_, int sec_) {
if (sec_ > fir_) fir_ = sec_;
}
void Chkmin(int &fir_, int sec_) {
if (sec_ < fir_) fir_ = sec_;
}
void AddEdge(int u_, int v_, int w_) {
v[++ e_num] = v_, w[e_num] = w_;
ne[e_num] = head[u_], head[u_] = e_num;
}
void Dfs(int u_, int fa_) {
dep[u_] = dep[fa_] + 1;
fa[u_][0] = fa_;
for (int i = 1; i <= 22; ++ i) {
fa[u_][i] = fa[fa[u_][i - 1]][i - 1];
sum[u_][i] = sum[u_][i - 1] + sum[fa[u_][i - 1]][i - 1];
}
for (int i = head[u_]; i; i = ne[i]) {
int v_ = v[i], w_ = w[i];
if (v_ == fa_) continue ;
sum[v_][0] = w_;
Dfs (v_, u_);
}
}
void GetLca(int id_, int u_, int v_) {
if (dep[v_] > dep[u_]) std :: swap(u_, v_);
for (int i = 22; i >= 0; -- i) {
if (dep[fa[u_][i]] >= dep[v_]) {
val[id_] += sum[u_][i];
u_ = fa[u_][i];
}
}
if (u_ == v_) {
lca[id_] = u_;
return ;
}
for (int i = 22; i >= 0; -- i) {
if (fa[u_][i] != fa[v_][i]) {
val[id_] += sum[u_][i] + sum[v_][i];
u_ = fa[u_][i];
v_ = fa[v_][i];
}
}
val[id_] += sum[u_][0] + sum[v_][0];
lca[id_] = fa[u_][0];
}
//=============================================================
int main() {
n = read(), m = read(), root = read();
for (int i = 1; i < n; ++ i) {
int u_ = read(), v_ = read(), w_ = 0;
AddEdge(u_, v_, w_), AddEdge(v_, u_, w_);
}
Dfs(root, 0);
for (int i = 1; i <= m; ++ i) {
a[i] = read(), b[i] = read();
GetLca(i, a[i], b[i]);
printf("%d\n", lca[i]);
}
return 0;
}
重链剖分
//
/*
By:Luckyblock
*/
#include <algorithm>
#include <cctype>
#include <cmath>
#include <cstdio>
#include <cstring>
#define ll long long
const int kMaxn = 5e5 + 10;
const int kMaxm = (kMaxn << 1);
//=============================================================
int n, m, root;
int e_num, head[kMaxn], v[kMaxn << 1], w[kMaxn << 1], ne[kMaxn << 1];
int size[kMaxn], dep[kMaxn], fa[kMaxn], top[kMaxn], son[kMaxn];
//=============================================================
inline int read() {
int f = 1, w = 0;
char ch = getchar();
for (; !isdigit(ch); ch = getchar())
if (ch == '-') f = -1;
for (; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
return f * w;
}
void Chkmax(int &fir_, int sec_) {
if (sec_ > fir_) fir_ = sec_;
}
void Chkmin(int &fir_, int sec_) {
if (sec_ < fir_) fir_ = sec_;
}
void AddEdge(int u_, int v_, int w_) {
v[++ e_num] = v_, w[e_num] = w_;
ne[e_num] = head[u_], head[u_] = e_num;
}
void Dfs1(int u_, int fa_) {
fa[u_] = fa_;
size[u_] = 1;
dep[u_] = dep[fa_] + 1;
for (int i = head[u_]; i; i = ne[i]) {
int v_ = v[i];
if (v_ == fa_) continue ;
Dfs1(v_, u_);
size[u_] += size[v_];
if (size[v_] > size[son[u_]]) son[u_] = v_;
}
}
void Dfs2(int u_, int top_) {
top[u_] = top_;
if (son[u_]) Dfs2(son[u_], top_);
for (int i = head[u_]; i; i = ne[i]) {
int v_ = v[i];
if (v_ == fa[u_] || v_ == son[u_]) continue ;
Dfs2(v_, v_);
}
}
int Lca(int u_, int v_) {
for (; top[u_] != top[v_]; u_ = fa[top[u_]]) {
if (dep[top[u_]] <= dep[top[v_]]) {
std::swap(u_, v_);
}
}
return dep[u_] < dep[v_] ? u_ : v_;
}
//=============================================================
int main() {
n = read(), m = read(), root = read();
for (int i = 1; i < n; ++ i) {
int u_ = read(), v_ = read(), w_ = 0;
AddEdge(u_, v_, w_), AddEdge(v_, u_, w_);
}
Dfs1(root, 0);
Dfs2(root, root);
for (int i = 1; i <= m; ++ i) {
int u_ = read(), v_ = read();
printf("%d\n", Lca(u_, v_));
}
return 0;
}
RMQ LCA 的大致思路
//
/*
By:Luckyblock
*/
#include <cstdio>
#include <cctype>
#include <algorithm>
#include <cmath>
#define ll long long
#define max std::max
const int MARX = 1e5 + 10;
//===========================================================
int N, M, Log2[MARX], MAX[MARX][25];
int node[MARX][25];
//===========================================================
inline int read()
{
int w = 0, f = 1; char ch = getchar();
for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1;
for(; isdigit(ch); ch = getchar()) w = (w << 3) + (w << 1) + (ch ^ '0');
return f * w;
}
void Prepare()
{
//MAX[i][j]: [i,i+2^j] max_num
N = read(), M = read();
for(int i = 1; i <= N; i ++) {
MAX[i][0] = dep[i];
node[i][0] = i;
}
for(int i = 2; i <= N; i ++) {
Log2[i] = Log2[i >> 1] + 1;
}
for(int i = 1; i <= 20; i ++)
for(int j = 1; j + (1 << i) - 1 <= N; j ++) {
if (MAX[j][i] < MAX[j + (1 << (i - 1))][i - 1]) {
MAX[j][i] = MAX[j][i - 1];
node[j][i] = node[j][i - 1];
} else {
MAX[j][i] = MAX[j + (1 << (i - 1))][i - 1];
node[j][i] = node[j + (1 << (i - 1))][i - 1];
}
}
}
int Query(int l, int r)
{
int Log = Log2[r - l + 1];
if (MAX[l][Log] < MAX[r - (1 << Log) + 1][Log]) return node[l][Log];
return node[r - (1 << Log) + 1][Log];
}
//===========================================================
int main()
{
printf("%lf", log(500000));
Prepare();
while(M --)
{
int l = read(), r =read();
printf("%d\n", Query(l, r));
}
return 0;
}
作者@Luckyblock,转载请声明出处。