ST
#include<bits/stdc++.h> using namespace std; const int N = 1e5 + 5; int dp[N][32]; int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int n, m; cin >> n >> m; for (int i = 1; i <= n; i++) cin >> dp[i][0]; for (int j = 1; j <= 20; j++) { for (int i = 1; i + (1 << j) - 1 <= n; i++) { dp[i][j] = max(dp[i][j - 1], dp[i + (1 << (j - 1))][j - 1]); } } while (m--) { int l, r; cin >> l >> r; int k = log2(r - l + 1); cout << max(dp[l][k], dp[r - (1 << k) + 1][k]) << '\n'; } return 0; }
LCA
// (n + m) log(m) #include<bits/stdc++.h> using namespace std; const int N = 5e5 + 5; int n, m, s; //樹的結點個數、詢問的個數和樹根結點的序號 int dep[N], f[N][20]; vector <int> adj[N]; void dfs(int from, int fa) { // from 是兒子 fa 是父親 dep[from] = dep[fa] + 1; f[from][0] = fa; //它的上一層是它的父親 for (int i = 1; i <= 19; i++) { f[from][i] = f[f[from][i - 1]][i - 1]; } for (int to : adj[from]) { if (to != fa) dfs(to, from); } } int lca(int from, int to) { // from 和 to 跳到同一層 if (dep[from] < dep[to]) swap(from, to); // 只讓from 跳 for (int i = 19; i >= 0; i--) { if (dep[f[from][i]] >= dep[to]) { from = f[from][i]; } } if (from == to) return to; //恰好to是它的祖先 for (int i = 19; i >= 0; i--) { if (f[from][i] != f[to][i]) { //如果不相同則讓它們走上去 from = f[from][i]; to = f[to][i]; } } return f[from][0]; } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n >> m >> s; for (int i = 1; i < n; i++) { int from, to; cin >> from >> to; adj[from].push_back(to); adj[to].push_back(from); } dfs(s, 0); while (m--) { int from, to; cin >> from >> to; cout << lca(from, to) << '\n'; } return 0; }
Trajan
// n + m #include<bits/stdc++.h> using namespace std; const int N = 5e5 + 5; int n, m, s, f[N], ans[N]; bool vis[N]; vector <int> adj[N]; vector <pair<int, int>> query[N]; int find(int x) { return f[x] == x ? x : f[x] = find(f[x]); } void Trajan(int from) { vis[from] = 1; for (int to : adj[from]) { if (!vis[to]) { Trajan(to); f[to] = from; } } for (auto [to, id] : query[from]) { if (vis[to]) ans[id] = find(to); } } int main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); cin >> n >> m >> s; for (int i = 1; i < n; i++) { int from, to; cin >> from >> to; adj[from].push_back(to); adj[to].push_back(from); } for (int i = 1; i <= m; i++) { int from, to; cin >> from >> to; query[from].push_back({to, i}); query[to].push_back({from, i}); } for (int i = 1; i < N; i++) f[i] = i; Trajan(s); for (int i = 1; i <= m; i++) cout << ans[i] << '\n'; return 0; }