Submission #395419

#TimeUsernameProblemLanguageResultExecution timeMemory
395419rama_pangBirthday gift (IZhO18_treearray)C++17
100 / 100
1936 ms79268 KiB
#include <bits/stdc++.h>
using namespace std;

int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);

  // Solution:
  // If A[] is a sequence, and LCA[] is all possible LCA(x, y) = LCA(A[x], A[x + 1], ..., A[y])
  // Then appending A[] with Z will only add possible LCA = LCA(A[-1], Z).
  // Why?
  // Consider W = LCA(A[-1], Z). Then A[-1] is in some subtree of child of W, Z is in another subtree of W.
  // All other possible LCA involving the new Z must be some ancestor of W. Let this ancestor be L, and
  // the segment be LCA(Y...Z).
  // But then, LCA(Y + 1, Z) != L, so Y and (Y + 1) must be in a different subtree of child of L, so
  // it is already added (LCA(Y, Y+1)).
  //
  // So, we only need to care about 2 adjacent elements in A[]. We can check the LCA() with binary lifting.
  // Time complexity: O(N log N).

  int N, M, Q;
  cin >> N >> M >> Q;

  vector<vector<int>> adj(N);
  for (int i = 1; i < N; i++) {
    int u, v;
    cin >> u >> v;
    u--, v--;
    adj[u].emplace_back(v);
    adj[v].emplace_back(u);
  }

  const int LOG = 18;
  vector<int> depth(N);
  vector<vector<int>> lift(LOG, vector<int>(N, -1));

  const auto Dfs = [&](const auto &self, int u, int p) -> void {
    lift[0][u] = p;
    for (int i = 1; i < LOG; i++) {
      lift[i][u] = lift[i - 1][u] == -1 ? -1 : lift[i - 1][lift[i - 1][u]];
    }
    for (auto v : adj[u]) if (v != p) {
      depth[v] = depth[u] + 1;
      self(self, v, u);
    }
  };
  Dfs(Dfs, 0, -1);

  const auto Lca = [&](int x, int y) {
    if (depth[x] > depth[y]) swap(x, y);

    int diff = depth[y] - depth[x];
    for (int i = 0; i < LOG; i++) {
      if ((diff >> i) & 1) {
        y = lift[i][y];
      }
    }

    assert(depth[x] == depth[y]);

    for (int i = LOG - 1; i >= 0; i--) {
      if (lift[i][x] != lift[i][y]) {
        x = lift[i][x];
        y = lift[i][y];
      }
    }
    return x == y ? x : lift[0][x];
  };

  vector<int> A(M);
  for (int i = 0; i < M; i++) {
    cin >> A[i];
    A[i]--;
  }

  vector<set<pair<int, int>>> ans(N);
  for (int i = 0; i < M; i++) {
    ans[A[i]].emplace(i, i);
  }
  for (int i = 1; i < M; i++) {
    ans[Lca(A[i - 1], A[i])].emplace(i - 1, i);
  }

  while (Q--) {
    int type;
    cin >> type;
    if (type == 1) {
      int i, v;
      cin >> i >> v;
      i--, v--;

      ans[A[i]].erase({i, i});
      if (i - 1 >= 0) ans[Lca(A[i - 1], A[i])].erase({i - 1, i});
      if (i + 1 <  M) ans[Lca(A[i], A[i + 1])].erase({i, i + 1});

      A[i] = v;

      ans[A[i]].insert({i, i});
      if (i - 1 >= 0) ans[Lca(A[i - 1], A[i])].insert({i - 1, i});
      if (i + 1 <  M) ans[Lca(A[i], A[i + 1])].insert({i, i + 1});
    } else if (type == 2) {
      int l, r, v;
      cin >> l >> r >> v;
      l--, r--, v--;
      auto it = ans[v].lower_bound({l, -1});
      if (it != end(ans[v]) && it->second <= r) {
        cout << it->first + 1 << ' ' << it->second + 1 << '\n';
      } else {
        cout << "-1 -1\n";
      }
    }
  }
  return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...