QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#748014#9570. Binary TreePlentyOfPenalty#ML 0ms3732kbC++203.4kb2024-11-14 19:02:182024-11-14 19:02:18

Judging History

你现在查看的是最新测评结果

  • [2024-11-14 19:02:18]
  • 评测
  • 测评结果:ML
  • 用时:0ms
  • 内存:3732kb
  • [2024-11-14 19:02:18]
  • 提交

answer

#include <bits/stdc++.h>
#define all(x) begin(x), end(x)
#define sz(x) ((int)(x).size())
#ifdef memset0
#define log(...) fprintf(stderr, __VA_ARGS__)
#else
#define endl '\n'
#define log(...) (void(0))
#endif
using namespace std;
using ll = long long;
using lf = long double;
using ull = unsigned long long;

const int N = 1e5 + 9;
int T, n, fa[N], dep[N], bo;
vector<int> g[N];

void dfs(int u) {
  for (int v : g[u])
    if (v != fa[u]) {
      fa[v] = u;
      dep[v] = dep[u] + 1;
      dfs(v);
    }
}

int get_dis(int u, int v) {
  int dis = 0;
  while (u != v) {
    if (dep[u] > dep[v]) swap(u, v);
    ++dis, v = fa[v];
  }
  return dis;
}

int _s = -1;
int ask(int u, int v) {
#ifdef memset0
  int s1 = get_dis(u, _s);
  int s2 = get_dis(v, _s);
  if (s1 < s2) return 0;
  if (s1 > s2) return 2;
  return 1;
#else
  cout << "? " << u << " " << v << endl;
  cout << flush;
  int x;
  cin >> x;
  return x;
#endif
}

bool vis[N];
vector<int> nod;

void markall(int u, int f) {
  vis[u] = true;
  for (int v : g[u])
    if (v != f && !vis[v]) {
      markall(v, u);
    }
}

tuple<int, int, int> cho;
int search(int u, int f) {
  int s = 1;
  for (int v : g[u])
    if (v != f && !vis[v]) {
      s += search(v, u);
    }
  if (f != -1) {
    if (sz(nod) - s >= s) {
      cho = min(cho, make_tuple(sz(nod) - s * 2, u, f));
    }
    if (s >= sz(nod) - s) {
      cho = min(cho, make_tuple(s * 2 - sz(nod), f, u));
    }
  }
  return s;
}

int solve() {
  log("!!! (internal) s = %d\n", _s);
  fill(vis + 1, vis + n + 1, false);
  while (true) {
    nod.clear();
    for (int i = 1; i <= n; i++)
      if (!vis[i]) {
        nod.emplace_back(i);
      }
    // fprintf(stderr, "loop >> sz=%d\n", sz(nod));
    if (sz(nod) == 1) {
      return nod[0];
    }
    if (sz(nod) == 2) {
      int u = nod[0], v = nod[1];
      int w = ask(u, v);
      return w == 0 ? u : v;
    }
    int rt = nod[0];
    for (int u : nod)
      if (dep[u] < dep[rt]) {
        rt = u;
      }
    auto &[diff, u, v] = cho;
    diff = INT_MAX;
    search(rt, -1);
    assert(diff <= 2);
    if (diff == 0) {
      int cho = ask(u, v);
      assert(cho != 1);
      if (cho == 0) {
        markall(v, u);
      } else {
        markall(u, v);
      }
    } else {
      int w = -1;
      for (int t : g[v])
        if (t != u && !vis[t]) {
          w = t;
          break;
        }
      assert(w != -1);
      int cho = ask(u, w);
      if (cho == 0) {
        markall(v, u);
      } else if (cho == 1) {
        markall(u, v);
        markall(w, v);
      } else if (cho == 2) {
        markall(v, w);
      }
    }
  }
}

int main() {
#ifdef memset0
  freopen("G.in", "r", stdin);
#endif
  cin.tie(0)->sync_with_stdio(0);
  cin >> T;
  while (T--) {
    cin >> n;
    for (int u, v, i = 1; i <= n; i++) {
      cin >> u >> v;
      if (u) {
        g[i].emplace_back(u);
        g[u].emplace_back(i);
      }
      if (v) {
        g[i].emplace_back(v);
        g[v].emplace_back(i);
      }
    }
    fill(fa + 1, fa + n + 1, 0);
    fill(dep + 1, dep + n + 1, 0);
    dep[1] = 1;
    dfs(1);
#ifdef memset0
    for (_s = 1; _s <= n; _s++) {
      int ans = solve();
      cout << "! " << ans << endl;
    }
#else
    int ans = solve();
    cout << "! " << ans << endl;
    cout << flush;
#endif
  }
}

詳細信息

Test #1:

score: 100
Accepted
time: 0ms
memory: 3732kb

input:

2
5
0 0
1 5
2 4
0 0
0 0
1
0
2
0 2
0 0
2

output:

? 3 1
? 2 5
! 2
? 1 2
! 2

result:

ok OK (2 test cases)

Test #2:

score: -100
Memory Limit Exceeded

input:

5555
8
2 0
8 6
0 0
3 0
0 0
7 0
0 0
5 4
2
0
2
8
0 0
1 4
2 0
0 0
7 8
0 0
3 0
6 0

output:

? 2 8
? 4 8
? 3 4
! 4

result: