█████████ ████ ███░░░░░███ ░░███ ███ ░░░ ██████ ███████ ██████ ██████ ░███ ███░░███ ███░░███ ███░░███ ███░░███ ░███ ░███ ░███░███ ░███ ░███████ ░███ ░███ ░░███ ███░███ ░███░███ ░███ ░███░░░ ░███ ░███ ░░█████████ ░░██████ ░░████████░░██████ ░░██████ ░░░░░░░░░ ░░░░░░ ░░░░░░░░ ░░░░░░ ░░░░░░

Envío 6844

Problema 0x1c - Decir si un nodo es ancestro de otro en un árbol

  • Autor: Juan Jr
  • Fecha: 2023-01-12 06:04:46 UTC (Hace casi 2 años)
Caso # Resultado Tiempo Memoria
#1
Correcto
0.004 s 3 KBi
#2
Correcto
0.005 s 6 KBi
#3
Correcto
0.007 s 1 KBi
#4
Correcto
0.005 s 1 KBi
#5
Correcto
0.005 s 5 KBi
#6
Correcto
0.004 s 1 KBi
#7
Correcto
0.004 s 4 KBi
#8
Correcto
0.005 s 1 KBi
#9
Correcto
0.005 s 7 KBi
#10
Correcto
0.004 s 1 KBi
#11
Correcto
0.008 s 1 KBi
#12
Correcto
0.119 s 10 KBi
#13
Correcto
0.127 s 10 KBi
#14
Correcto
0.125 s 10 KBi
#15
Correcto
0.131 s 10 KBi
#16
Correcto
0.101 s 24 KBi
#17
Correcto
0.106 s 18 KBi
#18
Correcto
0.129 s 18 KBi
#19
Correcto
0.096 s 16 KBi
#20
Correcto
0.101 s 16 KBi
Puntos totales: 100 / 100

Código

#include <bits/stdc++.h>
using namespace std;

typedef long long ll;
typedef pair<int, int> ii;
#define pb push_back
#define ff first
#define ss second
#define sz(x) int(x.size())
#define all(x) x.begin(), x.end()
#define forn(i, n) for (int i = 0; i < n; ++i)
#define rforn(i, n) for (int i = n; i >= 0; --i)
#define form(i, n, m, x) for (int i = n; i < m; i += x)
#define rform(i, n, m, x) for (int i = n; i >= m; i -= x)

#ifdef LOCAL
  #include "/debug/debug.h"
#else
  #define dbg(x...)
  #define endl '\n'
#endif

struct LCA {
  vector<int> height, euler, first, segtree;
  int n;

  LCA(vector<vector<int>> &g, int root = 0) {
    n = sz(g);
    height.resize(n);
    first.resize(n);
    dfs(g, root, root);
    int m = sz(euler);
    segtree.resize(m * 4);
    build(1, 0, m - 1);
  }

  void dfs(vector<vector<int>> &g, int v, int p, int h = 0) {
    height[v] = h;
    first[v] = sz(euler);
    euler.pb(v);
    for (int &u : g[v]) {
      if (u == p) continue;
      dfs(g, u, v, h + 1);
      euler.pb(v);
    }
  }

  void build(int node, int b, int e) {
    if (b == e) {
      segtree[node] = euler[b];
    } else {
      int mid = (b + e) / 2;
      build(node << 1, b, mid);
      build(node << 1 | 1, mid + 1, e);
      int l = segtree[node << 1], r = segtree[node << 1 | 1];
      segtree[node] = (height[l] < height[r]) ? l : r;
    }
  }

  int query(int node, int b, int e, int L, int R) {
    if (b > R || e < L) return -1;
    if (b >= L && e <= R) return segtree[node];
    int mid = (b + e) >> 1;
    int left = query(node << 1, b, mid, L, R);
    int right = query(node << 1 | 1, mid + 1, e, L, R);
    if (left == -1) return right;
    if (right == -1) return left;
    return height[left] < height[right] ? left : right;
  }

  int lca(int u, int v) {
    int left = first[u], right = first[v];
    if (left > right) swap(left, right);
    return query(1, 0, sz(euler) - 1, left, right);
  }
};

int main() {
  ios_base::sync_with_stdio(false);
  cin.tie(0);
  int n; cin >> n;
  vector<vector<int>> g(n);
  forn (i, n - 1) {
    int v, u; cin >> v >> u;
    g[v].pb(u);
  }
  LCA l(g);
  int q; cin >> q;
  while (q--) {
    int v, u; cin >> v >> u;
    cout << (l.lca(v, u) == v ? "Yes" : "No") << endl;
  }
  return 0;
}

/* stuff you should look for
 * int overflow, array bounds
 * special cases (n=1?)
 * do smth instead of nothing and stay organized
 * WRITE STUFF DOWN
 * DON'T GET STUCK ON ONE APPROACH
 */