「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;
}
posted @ 2020-10-28 10:15  Luckyblock  阅读(172)  评论(0编辑  收藏  举报