Submission #636979

#TimeUsernameProblemLanguageResultExecution timeMemory
636979abekerPrize (CEOI22_prize)C++17
100 / 100
2958 ms391168 KiB
#include <bits/stdc++.h>
using namespace std;

typedef pair <int, int> pii;

class Tree {
  int n, lg, root;
  vector <vector <int>> ch, anc;
  vector <int> dist, dep;
public:
  Tree(int n) : n(n) {
    for (lg = 0; 1 << lg < n; lg++);
    ch.resize(n + 1);
    anc.resize(n + 1, vector <int> (lg + 1));
    dist.resize(n + 1);
    dep.resize(n + 1);
    for (int i = 1; i <= n; i++) {
      scanf("%d", &anc[i][0]);
      if (anc[i][0] == -1) {
        anc[i][0] = 0;
        root = i;
      }
      else
        ch[anc[i][0]].push_back(i);
    }
  }
  Tree() {}
  void getSubset(int x, int k, vector <int> &v) {
    if (v.size() == k)
      return;
    v.push_back(x);
    for (auto it : ch[x])
      getSubset(it, k, v);
  }
  vector <int> getSubset(int k) {
    vector <int> res;
    getSubset(root, k, res);
    return res;
  }
  void getOrder(int x, vector <int> &v, const vector <bool> &in) {
    if (in[x])
      v.push_back(x);
    for (auto it : ch[x])
      getOrder(it, v, in);
  }
  vector <int> getOrder(const vector <int> &subset) {
    vector <bool> tmp(n + 1);
    for (auto it : subset)
      tmp[it] = true;
    vector <int> res;
    getOrder(root, res, tmp);
    return res;
  }
  int lca(int a, int b) {
    if (dep[a] < dep[b])
      swap(a, b);
    int diff = dep[a] - dep[b];
    for (int i = 0; i <= lg; i++)
      if (diff >> i & 1)
        a = anc[a][i];
    if (a == b)
      return a;
    for (int i = lg; i >= 0; i--)
      if (anc[a][i] != anc[b][i]) {
        a = anc[a][i];
        b = anc[b][i];
      }
    return anc[a][0];
  }
  void init(const vector <int> &order, const vector <pii> &ans) {
    for (int j = 1; j <= lg; j++)
      for (int i = 1; i <= n; i++)
        anc[i][j] = anc[anc[i][j - 1]][j - 1];
    queue <int> q;
    q.push(root);
    while (!q.empty()) {
      int x = q.front();
      q.pop();
      for (auto it : ch[x]) {
        dep[it] = dep[x] + 1;
        q.push(it);
      }
    }
    vector <int> l;
    for (int i = 1; i < order.size(); i++)
      l.push_back(lca(order[i - 1], order[i]));
    int pos = min_element(l.begin(), l.end(), [&](int x, int y) { return dep[x] < dep[y]; }) - l.begin();
    dist[order[pos]] = ans[pos].first;
    dist[order[pos + 1]] = ans[pos].second;
    for (int i = pos - 1; i >= 0; i--)
      dist[order[i]] = dist[order[i + 1]] - ans[i].second + ans[i].first;
    for (int i = pos + 2; i < order.size(); i++)
      dist[order[i]] = dist[order[i - 1]] - ans[i - 1].first + ans[i - 1].second;
    for (int i = 0; i < l.size(); i++)
      dist[l[i]] = dist[order[i]] - ans[i].first;
  }
  int getDistance(int a, int b) {
    int l = lca(a, b);
    return (dist[a] - dist[l]) + (dist[b] - dist[l]);
  }
};

int N, K, Q, T;
Tree one, two;

void load() {
  scanf("%d%d%d%d", &N, &K, &Q, &T);
  one = Tree(N);
  two = Tree(N);
}

void solve() {
  vector <int> subset = two.getOrder(one.getSubset(K));
  for (auto it : subset)
    printf("%d ", it);
  puts("");
  fflush(stdout);
  for (int i = 1; i < K; i++)
    printf("? %d %d\n", subset[i - 1], subset[i]);
  puts("!");
  fflush(stdout);
  vector <pii> ans_one, ans_two;
  for (int i = 1; i < K; i++) {
    int x, y, z, w;
    scanf("%d%d%d%d", &x, &y, &z, &w);
    ans_one.push_back({x, y});
    ans_two.push_back({z, w});
  }
  one.init(subset, ans_one);
  two.init(subset, ans_two);
  vector <pii> queries(T);
  for (auto &it : queries)
    scanf("%d%d", &it.first, &it.second);
  for (auto it : queries)
    printf("%d %d\n", one.getDistance(it.first, it.second), two.getDistance(it.first, it.second));
  fflush(stdout);
}

int main() {
  load();
  solve();
  return 0;
}

Compilation message (stderr)

Main.cpp: In member function 'void Tree::getSubset(int, int, std::vector<int>&)':
Main.cpp:29:18: warning: comparison of integer expressions of different signedness: 'std::vector<int>::size_type' {aka 'long unsigned int'} and 'int' [-Wsign-compare]
   29 |     if (v.size() == k)
      |         ~~~~~~~~~^~~~
Main.cpp: In member function 'void Tree::init(const std::vector<int>&, const std::vector<std::pair<int, int> >&)':
Main.cpp:85:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   85 |     for (int i = 1; i < order.size(); i++)
      |                     ~~^~~~~~~~~~~~~~
Main.cpp:92:29: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   92 |     for (int i = pos + 2; i < order.size(); i++)
      |                           ~~^~~~~~~~~~~~~~
Main.cpp:94:23: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
   94 |     for (int i = 0; i < l.size(); i++)
      |                     ~~^~~~~~~~~~
Main.cpp: In function 'void load()':
Main.cpp:107:8: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  107 |   scanf("%d%d%d%d", &N, &K, &Q, &T);
      |   ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
Main.cpp: In constructor 'Tree::Tree(int)':
Main.cpp:18:12: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
   18 |       scanf("%d", &anc[i][0]);
      |       ~~~~~^~~~~~~~~~~~~~~~~~
Main.cpp: In function 'void solve()':
Main.cpp:125:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  125 |     scanf("%d%d%d%d", &x, &y, &z, &w);
      |     ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~
Main.cpp:133:10: warning: ignoring return value of 'int scanf(const char*, ...)' declared with attribute 'warn_unused_result' [-Wunused-result]
  133 |     scanf("%d%d", &it.first, &it.second);
      |     ~~~~~^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...