#include <bits/stdc++.h>
using namespace std;
struct seg_t {
  vector<int> d;
  int N;
  int size() const { return N - 1; }
  void resize(int N_) {
    N = N_;
    d.resize(7 * N);
  }
  void set(int idx, int v, int a, int b, int i) {
    if (idx < a || idx > b) return;
    assert(i < (int)d.size());
    d[i] = max(d[i], v);
    if (a == b) return;
    int m = (a + b) / 2;
    set(idx, v, a, m, (2 * (i)));
    set(idx, v, m + 1, b, (2 * (i) + 1));
  }
  int get_max(int low, int high, int a, int b, int i) {
    if (high < a || low > b) return -1000000;
    if (low <= a && b <= high) return d[i];
    int m = (a + b) / 2;
    return max(get_max(low, high, a, m, (2 * (i))),
               get_max(low, high, m + 1, b, (2 * (i) + 1)));
  }
};
struct rmq_t {
  seg_t asc, desc;
  int N;
  int size() const { return N - 1; }
  void resize(int N_) {
    N = N_;
    asc.resize(N);
    desc.resize(N);
  }
  int query_asc(int a, int b) { return asc.get_max(a, b, 1, N, 1); }
  int query_desc(int a, int b) { return desc.get_max(a, b, 1, N, 1); }
  void set(int idx, int v) {
    assert(1 <= idx && idx <= size());
    asc.set(idx, v + idx - 1, 1, N, 1);
    desc.set(idx, v + size() - idx, 1, N, 1);
  }
};
struct hld_node_t {
  int parent, depth, fr, ofr;
  int weight, path, idx, height, second_height, third_height;
  int next, previdx;
  bool is_child;
};
void hld_set_parent(int i, int p, hld_node_t* H) {
  H[i].parent = p;
  H[i].depth = H[p].depth + 1;
  H[i].is_child = true;
}
void hld_dfs(int i, vector<int>* E, hld_node_t* H) {
  int numE = E[i].size(), j;
  H[i].weight = 1;
  H[i].height = 0, H[i].second_height = -1000000, H[i].third_height = -1000000;
  for (int x = 0; x < (numE); ++x) {
    if ((j = E[i][x]) == H[i].parent) continue;
    H[j].fr = H[j].ofr = x;
    hld_set_parent(j, i, H), hld_dfs(j, E, H);
    H[i].weight += H[j].weight;
    if (H[j].height >= H[i].height)
      H[i].third_height = H[i].second_height, H[i].second_height = H[i].height,
      H[i].height = H[j].height + 1;
    else if (H[j].height >= H[i].second_height)
      H[i].third_height = H[i].second_height,
      H[i].second_height = H[j].height + 1;
    else if (H[j].height >= H[i].third_height)
      H[i].third_height = H[j].height + 1;
  }
  H[i].path = i, H[i].idx = 1, H[i].previdx = -1;
  for (int x = 0; x < (numE); ++x) {
    if ((j = E[i][x]) == H[i].parent) continue;
    if (2 * H[j].weight >= H[i].weight)
      H[i].path = H[j].path, H[i].idx = H[j].idx + 1, H[i].previdx = x;
  }
}
void hld_dfs2(int i, vector<int>* E, hld_node_t* H, bool heavy = false) {
  H[i].next =
      (H[i].is_child ? (heavy ? H[H[i].parent].next : H[i].parent) : -1);
  if (H[i].next != H[i].parent)
    H[i].fr = (H[i].is_child ? H[H[i].parent].fr : -1);
  int numE = E[i].size(), j;
  for (int x = 0; x < (numE); ++x) {
    if ((j = E[i][x]) == H[i].parent) continue;
    hld_dfs2(j, E, H, (2 * H[j].weight >= H[i].weight));
  }
}
template <class structure>
void hld_resize(int i, vector<int>* E, hld_node_t* H, structure* A) {
  if (H[i].parent < 0 || H[H[i].parent].path != H[i].path)
    A[H[i].path].resize(H[i].idx + 1);
  int numE = E[i].size(), j;
  for (int x = 0; x < (numE); ++x)
    if ((j = E[i][x]) != H[i].parent) hld_resize(j, E, H, A);
}
template <class structure>
void hld_init(int root, vector<int>* E, hld_node_t* H, structure* A) {
  hld_dfs(root, E, H);
  hld_dfs2(root, E, H);
  hld_resize(root, E, H, A);
}
int get_height(int i, int fr, hld_node_t* H, vector<int>* E) {
  if (fr < 0) return H[i].height;
  assert(fr < (int)E[i].size());
  int j = E[i][fr];
  if (H[j].height + 1 == H[i].height)
    return H[i].second_height;
  else
    return H[i].height;
}
int get_height(int i, int fr1, int fr2, hld_node_t* H, vector<int>* E) {
  if (fr1 < 0 || fr2 < 0) return H[i].height;
  assert(fr1 < (int)E[i].size() && fr2 < (int)E[i].size());
  int j = E[i][fr1];
  int k = E[i][fr2];
  if (H[j].height < H[k].height) swap(j, k);
  if (H[j].height + 1 < H[i].height) return H[i].height;
  assert(H[j].height + 1 == H[i].height);
  if (H[k].height + 1 == H[i].second_height) return H[i].third_height;
  assert(H[k].height + 1 < H[i].second_height);
  return H[i].second_height;
}
template <class structure>
int hld_query(int i, int itop, int fr, hld_node_t* H, vector<int>* E,
              structure A[]) {
  if (i <= 0 || itop <= 0) return -1000000;
  if (H[i].depth < H[itop].depth) return -1000000;
  int ans = 0, tmp = 0, d = H[i].depth;
  for (; i >= 0 && H[i].depth >= H[itop].depth; fr = H[i].fr, i = H[i].next) {
    int endidx =
        (H[i].path == H[itop].path) ? H[itop].idx : A[H[i].path].size();
    tmp = A[H[i].path].query_asc(H[i].idx + 1, endidx) - (H[i].idx - 1);
    tmp = max(tmp, get_height(i, fr, H, E));
    ans = max(ans, tmp + d - H[i].depth);
  }
  return ans;
}
template <class structure>
int hld_query_desc(int i, int itop, int fr, hld_node_t* H, vector<int>* E,
                   structure A[]) {
  if (i <= 0 || itop <= 0) return -1000000;
  if (H[i].depth < H[itop].depth) return -1000000;
  int ans = 0, tmp = 0;
  for (; i >= 0 && H[i].depth >= H[itop].depth; fr = H[i].fr, i = H[i].next) {
    int endidx =
        (H[i].path == H[itop].path) ? H[itop].idx : A[H[i].path].size();
    tmp = A[H[i].path].query_desc(H[i].idx + 1, endidx) -
          (A[H[i].path].size() - endidx);
    tmp = max(tmp, get_height(i, fr, H, E) + endidx - H[i].idx);
    ans = max(ans, tmp + (H[i].depth - H[itop].depth) - (endidx - H[i].idx));
  }
  return ans;
}
hld_node_t H[100005];
vector<int> E[100005];
rmq_t A[100005];
int lca[100005][17];
int nth_parent(int a, int n) {
  assert(n >= 0);
  for (int k = 0; n; n >>= 1, ++k)
    if (n & 1) a = lca[a][k];
  return a;
}
int get_lca(int a, int b) {
  if (H[a].depth < H[b].depth) swap(a, b);
  a = nth_parent(a, H[a].depth - H[b].depth);
  assert(H[a].depth == H[b].depth);
  for (int k = 17 - 1; k >= 0; --k)
    if (lca[a][k] != lca[b][k]) a = lca[a][k], b = lca[b][k];
  if (a != b) {
    assert(H[a].parent == H[b].parent);
    a = b = H[a].parent;
  }
  return a;
}
int just_before(int a, int b) {
  assert(get_lca(a, b) == b);
  int dist = H[a].depth - H[b].depth;
  assert(dist >= 0);
  return (dist > 0 ? nth_parent(a, dist - 1) : -1);
}
int query(int a, int b) {
  if (H[a].depth < H[b].depth) swap(a, b);
  int c = get_lca(a, b);
  int ac = H[a].depth - H[c].depth, bc = H[b].depth - H[c].depth;
  assert(ac >= 0 && bc >= 0 && ac >= bc);
  int dist = ac + bc;
  int atop = nth_parent(a, (dist + 1) / 2);
  int batop = just_before(a, atop);
  assert(H[atop].depth >= H[c].depth);
  if (a == b) {
    int ans = hld_query(a, 1, -1, H, E, A);
    return ans;
  } else if (b == c) {
    int jbf = just_before(a, b);
    int ans = hld_query(a, batop, -1, H, E, A);
    ans = max(ans, hld_query_desc(atop, jbf, H[batop].ofr, H, E, A) + 1);
    ans = max(ans, hld_query(b, 1, H[jbf].ofr, H, E, A));
    return ans;
  } else {
    assert(a != c);
    int jaf = just_before(a, c);
    int jbf = just_before(b, c);
    int ans = hld_query(a, batop, -1, H, E, A);
    ans = max(ans, hld_query_desc(atop, jaf, H[batop].ofr, H, E, A) + bc + 1);
    ans = max(ans, hld_query(b, jbf, -1, H, E, A));
    ans = max(ans, hld_query(H[c].parent, 1, H[c].ofr, H, E, A) + bc + 1);
    assert(H[jaf].parent == c && H[jbf].parent == c);
    ans = max(ans, get_height(c, H[jaf].ofr, H[jbf].ofr, H, E) + bc);
    return ans;
  }
}
int main() {
  int N, M, a, b;
  cin >> N;
  for (int i = 0; i < (N - 1); ++i) {
    scanf("%d%d", &a, &b);
    E[a].push_back(b);
    E[b].push_back(a);
  }
  hld_init(1, E, H, A);
  for (int i = (1); i <= (N); ++i) {
    A[H[i].path].set(H[i].idx, get_height(i, H[i].previdx, H, E));
  }
  for (int i = (1); i <= (N); ++i) lca[i][0] = H[i].parent;
  for (int k = (0); k <= (17 - 2); ++k)
    for (int i = (1); i <= (N); ++i) lca[i][k + 1] = lca[lca[i][k]][k];
  cin >> M;
  for (int i = 0; i < (M); ++i) {
    scanf("%d%d", &a, &b);
    printf("%d\n", query(a, b));
  }
}

### Prompt

Please provide a CPP coded solution to the problem described below:

The Finals of the "Russian Code Cup" 2214 will be held in n hotels. Two hotels (let's assume that they are the main hotels), will host all sorts of events, and the remaining hotels will accommodate the participants. The hotels are connected by n - 1 roads, you can get from any hotel to any other one.

The organizers wonder what is the minimum time all the participants need to get to the main hotels, if each participant goes to the main hotel that is nearest to him and moving between two hotels connected by a road takes one unit of time.

The hosts consider various options for the location of the main hotels. For each option help the organizers to find minimal time.

Input

The first line contains an integer n (2 ≤ n ≤ 100000) — the number of hotels. The next n - 1 lines contain two integers each — the numbers of the hotels that have a road between them. Consider hotels are numbered from 1 to n.

The next line contains an integer m (1 ≤ m ≤ 100000) — the number of queries. The following m lines contains two distinct integers each — the numbers of the hotels we assume to be the main.

Output

For each request of the organizers print a single integer — the time that all participants need to reach the main hotels.

Examples

Input

3
2 3
3 1
3
2 1
2 3
3 1


Output

1
1
1


Input

4
1 4
1 2
2 3
3
1 4
1 3
2 3


Output

2
1
2

### Response

```cpp
#include <bits/stdc++.h>
using namespace std;
struct seg_t {
  vector<int> d;
  int N;
  int size() const { return N - 1; }
  void resize(int N_) {
    N = N_;
    d.resize(7 * N);
  }
  void set(int idx, int v, int a, int b, int i) {
    if (idx < a || idx > b) return;
    assert(i < (int)d.size());
    d[i] = max(d[i], v);
    if (a == b) return;
    int m = (a + b) / 2;
    set(idx, v, a, m, (2 * (i)));
    set(idx, v, m + 1, b, (2 * (i) + 1));
  }
  int get_max(int low, int high, int a, int b, int i) {
    if (high < a || low > b) return -1000000;
    if (low <= a && b <= high) return d[i];
    int m = (a + b) / 2;
    return max(get_max(low, high, a, m, (2 * (i))),
               get_max(low, high, m + 1, b, (2 * (i) + 1)));
  }
};
struct rmq_t {
  seg_t asc, desc;
  int N;
  int size() const { return N - 1; }
  void resize(int N_) {
    N = N_;
    asc.resize(N);
    desc.resize(N);
  }
  int query_asc(int a, int b) { return asc.get_max(a, b, 1, N, 1); }
  int query_desc(int a, int b) { return desc.get_max(a, b, 1, N, 1); }
  void set(int idx, int v) {
    assert(1 <= idx && idx <= size());
    asc.set(idx, v + idx - 1, 1, N, 1);
    desc.set(idx, v + size() - idx, 1, N, 1);
  }
};
struct hld_node_t {
  int parent, depth, fr, ofr;
  int weight, path, idx, height, second_height, third_height;
  int next, previdx;
  bool is_child;
};
void hld_set_parent(int i, int p, hld_node_t* H) {
  H[i].parent = p;
  H[i].depth = H[p].depth + 1;
  H[i].is_child = true;
}
void hld_dfs(int i, vector<int>* E, hld_node_t* H) {
  int numE = E[i].size(), j;
  H[i].weight = 1;
  H[i].height = 0, H[i].second_height = -1000000, H[i].third_height = -1000000;
  for (int x = 0; x < (numE); ++x) {
    if ((j = E[i][x]) == H[i].parent) continue;
    H[j].fr = H[j].ofr = x;
    hld_set_parent(j, i, H), hld_dfs(j, E, H);
    H[i].weight += H[j].weight;
    if (H[j].height >= H[i].height)
      H[i].third_height = H[i].second_height, H[i].second_height = H[i].height,
      H[i].height = H[j].height + 1;
    else if (H[j].height >= H[i].second_height)
      H[i].third_height = H[i].second_height,
      H[i].second_height = H[j].height + 1;
    else if (H[j].height >= H[i].third_height)
      H[i].third_height = H[j].height + 1;
  }
  H[i].path = i, H[i].idx = 1, H[i].previdx = -1;
  for (int x = 0; x < (numE); ++x) {
    if ((j = E[i][x]) == H[i].parent) continue;
    if (2 * H[j].weight >= H[i].weight)
      H[i].path = H[j].path, H[i].idx = H[j].idx + 1, H[i].previdx = x;
  }
}
void hld_dfs2(int i, vector<int>* E, hld_node_t* H, bool heavy = false) {
  H[i].next =
      (H[i].is_child ? (heavy ? H[H[i].parent].next : H[i].parent) : -1);
  if (H[i].next != H[i].parent)
    H[i].fr = (H[i].is_child ? H[H[i].parent].fr : -1);
  int numE = E[i].size(), j;
  for (int x = 0; x < (numE); ++x) {
    if ((j = E[i][x]) == H[i].parent) continue;
    hld_dfs2(j, E, H, (2 * H[j].weight >= H[i].weight));
  }
}
template <class structure>
void hld_resize(int i, vector<int>* E, hld_node_t* H, structure* A) {
  if (H[i].parent < 0 || H[H[i].parent].path != H[i].path)
    A[H[i].path].resize(H[i].idx + 1);
  int numE = E[i].size(), j;
  for (int x = 0; x < (numE); ++x)
    if ((j = E[i][x]) != H[i].parent) hld_resize(j, E, H, A);
}
template <class structure>
void hld_init(int root, vector<int>* E, hld_node_t* H, structure* A) {
  hld_dfs(root, E, H);
  hld_dfs2(root, E, H);
  hld_resize(root, E, H, A);
}
int get_height(int i, int fr, hld_node_t* H, vector<int>* E) {
  if (fr < 0) return H[i].height;
  assert(fr < (int)E[i].size());
  int j = E[i][fr];
  if (H[j].height + 1 == H[i].height)
    return H[i].second_height;
  else
    return H[i].height;
}
int get_height(int i, int fr1, int fr2, hld_node_t* H, vector<int>* E) {
  if (fr1 < 0 || fr2 < 0) return H[i].height;
  assert(fr1 < (int)E[i].size() && fr2 < (int)E[i].size());
  int j = E[i][fr1];
  int k = E[i][fr2];
  if (H[j].height < H[k].height) swap(j, k);
  if (H[j].height + 1 < H[i].height) return H[i].height;
  assert(H[j].height + 1 == H[i].height);
  if (H[k].height + 1 == H[i].second_height) return H[i].third_height;
  assert(H[k].height + 1 < H[i].second_height);
  return H[i].second_height;
}
template <class structure>
int hld_query(int i, int itop, int fr, hld_node_t* H, vector<int>* E,
              structure A[]) {
  if (i <= 0 || itop <= 0) return -1000000;
  if (H[i].depth < H[itop].depth) return -1000000;
  int ans = 0, tmp = 0, d = H[i].depth;
  for (; i >= 0 && H[i].depth >= H[itop].depth; fr = H[i].fr, i = H[i].next) {
    int endidx =
        (H[i].path == H[itop].path) ? H[itop].idx : A[H[i].path].size();
    tmp = A[H[i].path].query_asc(H[i].idx + 1, endidx) - (H[i].idx - 1);
    tmp = max(tmp, get_height(i, fr, H, E));
    ans = max(ans, tmp + d - H[i].depth);
  }
  return ans;
}
template <class structure>
int hld_query_desc(int i, int itop, int fr, hld_node_t* H, vector<int>* E,
                   structure A[]) {
  if (i <= 0 || itop <= 0) return -1000000;
  if (H[i].depth < H[itop].depth) return -1000000;
  int ans = 0, tmp = 0;
  for (; i >= 0 && H[i].depth >= H[itop].depth; fr = H[i].fr, i = H[i].next) {
    int endidx =
        (H[i].path == H[itop].path) ? H[itop].idx : A[H[i].path].size();
    tmp = A[H[i].path].query_desc(H[i].idx + 1, endidx) -
          (A[H[i].path].size() - endidx);
    tmp = max(tmp, get_height(i, fr, H, E) + endidx - H[i].idx);
    ans = max(ans, tmp + (H[i].depth - H[itop].depth) - (endidx - H[i].idx));
  }
  return ans;
}
hld_node_t H[100005];
vector<int> E[100005];
rmq_t A[100005];
int lca[100005][17];
int nth_parent(int a, int n) {
  assert(n >= 0);
  for (int k = 0; n; n >>= 1, ++k)
    if (n & 1) a = lca[a][k];
  return a;
}
int get_lca(int a, int b) {
  if (H[a].depth < H[b].depth) swap(a, b);
  a = nth_parent(a, H[a].depth - H[b].depth);
  assert(H[a].depth == H[b].depth);
  for (int k = 17 - 1; k >= 0; --k)
    if (lca[a][k] != lca[b][k]) a = lca[a][k], b = lca[b][k];
  if (a != b) {
    assert(H[a].parent == H[b].parent);
    a = b = H[a].parent;
  }
  return a;
}
int just_before(int a, int b) {
  assert(get_lca(a, b) == b);
  int dist = H[a].depth - H[b].depth;
  assert(dist >= 0);
  return (dist > 0 ? nth_parent(a, dist - 1) : -1);
}
int query(int a, int b) {
  if (H[a].depth < H[b].depth) swap(a, b);
  int c = get_lca(a, b);
  int ac = H[a].depth - H[c].depth, bc = H[b].depth - H[c].depth;
  assert(ac >= 0 && bc >= 0 && ac >= bc);
  int dist = ac + bc;
  int atop = nth_parent(a, (dist + 1) / 2);
  int batop = just_before(a, atop);
  assert(H[atop].depth >= H[c].depth);
  if (a == b) {
    int ans = hld_query(a, 1, -1, H, E, A);
    return ans;
  } else if (b == c) {
    int jbf = just_before(a, b);
    int ans = hld_query(a, batop, -1, H, E, A);
    ans = max(ans, hld_query_desc(atop, jbf, H[batop].ofr, H, E, A) + 1);
    ans = max(ans, hld_query(b, 1, H[jbf].ofr, H, E, A));
    return ans;
  } else {
    assert(a != c);
    int jaf = just_before(a, c);
    int jbf = just_before(b, c);
    int ans = hld_query(a, batop, -1, H, E, A);
    ans = max(ans, hld_query_desc(atop, jaf, H[batop].ofr, H, E, A) + bc + 1);
    ans = max(ans, hld_query(b, jbf, -1, H, E, A));
    ans = max(ans, hld_query(H[c].parent, 1, H[c].ofr, H, E, A) + bc + 1);
    assert(H[jaf].parent == c && H[jbf].parent == c);
    ans = max(ans, get_height(c, H[jaf].ofr, H[jbf].ofr, H, E) + bc);
    return ans;
  }
}
int main() {
  int N, M, a, b;
  cin >> N;
  for (int i = 0; i < (N - 1); ++i) {
    scanf("%d%d", &a, &b);
    E[a].push_back(b);
    E[b].push_back(a);
  }
  hld_init(1, E, H, A);
  for (int i = (1); i <= (N); ++i) {
    A[H[i].path].set(H[i].idx, get_height(i, H[i].previdx, H, E));
  }
  for (int i = (1); i <= (N); ++i) lca[i][0] = H[i].parent;
  for (int k = (0); k <= (17 - 2); ++k)
    for (int i = (1); i <= (N); ++i) lca[i][k + 1] = lca[lca[i][k]][k];
  cin >> M;
  for (int i = 0; i < (M); ++i) {
    scanf("%d%d", &a, &b);
    printf("%d\n", query(a, b));
  }
}

```