CodeForces-1706E.cpp 2.7 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374
  1. #include <algorithm>
  2. #include <iostream>
  3. #include <numeric>
  4. #include <utility>
  5. #include <vector>
  6. using namespace std;
  7. int main() {
  8. ios::sync_with_stdio(false);
  9. cin.tie(nullptr);
  10. int tests; cin >> tests;
  11. while (tests--) {
  12. int n, m, queries; cin >> n >> m >> queries;
  13. vector<int> dsu(2 * n), value(2 * n, 0);
  14. iota(dsu.begin(), dsu.end(), 0);
  15. vector<vector<int>> child(2 * n);
  16. auto find = [&](auto &&self, int x) -> int {
  17. return dsu[x] == x ? x : dsu[x] = self(self, dsu[x]);
  18. };
  19. int nodes = n;
  20. for (int index = 1; index <= m; ++index) {
  21. int u, v; cin >> u >> v; --u; --v;
  22. int a = find(find, u), b = find(find, v);
  23. if (a == b) continue;
  24. value[nodes] = index;
  25. child[nodes] = {a, b};
  26. dsu[a] = dsu[b] = nodes;
  27. dsu[nodes] = nodes;
  28. ++nodes;
  29. }
  30. int root = find(find, 0), log = 1;
  31. while ((1 << log) <= nodes) ++log;
  32. vector<vector<int>> up(log, vector<int>(nodes, root));
  33. vector<int> depth(nodes, 0), stack{root};
  34. while (!stack.empty()) {
  35. int u = stack.back(); stack.pop_back();
  36. for (int v : child[u]) {
  37. up[0][v] = u; depth[v] = depth[u] + 1; stack.push_back(v);
  38. }
  39. }
  40. up[0][root] = root;
  41. for (int j = 1; j < log; ++j) for (int v = 0; v < nodes; ++v) {
  42. up[j][v] = up[j - 1][up[j - 1][v]];
  43. }
  44. auto lca = [&](int u, int v) {
  45. if (depth[u] < depth[v]) swap(u, v);
  46. for (int j = log - 1; j >= 0; --j) if (depth[u] - (1 << j) >= depth[v]) u = up[j][u];
  47. if (u == v) return u;
  48. for (int j = log - 1; j >= 0; --j) if (up[j][u] != up[j][v]) {
  49. u = up[j][u]; v = up[j][v];
  50. }
  51. return up[0][u];
  52. };
  53. int size = 1;
  54. while (size < max(1, n - 1)) size <<= 1;
  55. vector<int> segment(2 * size, 0);
  56. for (int i = 0; i + 1 < n; ++i) segment[size + i] = value[lca(i, i + 1)];
  57. for (int i = size - 1; i > 0; --i) segment[i] = max(segment[2 * i], segment[2 * i + 1]);
  58. auto range_max = [&](int left, int right) {
  59. int answer = 0;
  60. for (left += size, right += size; left < right; left >>= 1, right >>= 1) {
  61. if (left & 1) answer = max(answer, segment[left++]);
  62. if (right & 1) answer = max(answer, segment[--right]);
  63. }
  64. return answer;
  65. };
  66. while (queries--) {
  67. int l, r; cin >> l >> r; --l;
  68. cout << (l + 1 == r ? 0 : range_max(l, r - 1)) << ' ';
  69. }
  70. cout << '\n';
  71. }
  72. }