QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#735840#9570. Binary TreeJ1angZ1TL 1ms3860kbC++205.1kb2024-11-11 22:01:462024-11-11 22:01:46

Judging History

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

  • [2024-11-11 22:01:46]
  • 评测
  • 测评结果:TL
  • 用时:1ms
  • 内存:3860kb
  • [2024-11-11 22:01:46]
  • 提交

answer

#include <bits/stdc++.h>
using namespace std;

#ifdef LOCAL
#include "debug.h"
#else
#define debug(...) 0
#endif

using i64 = long long;
struct Tree {
    int n;
    vector<vector<pair<int, int>>> e;
    vector<int> dep, parent, maxdep, d1, d2, s1, s2, up;
    Tree(int n) {
        this->n = n;
        e.resize(n + 1);
        dep.resize(n + 1);
        parent.resize(n + 1);
        maxdep.resize(n + 1);
        d1.resize(n + 1);
        d2.resize(n + 1);
        s1.resize(n + 1);
        s2.resize(n + 1);
        up.resize(n + 1);
    }
    void add(int u, int v, int w) {
        e[u].push_back({w, v});
        e[v].push_back({w, u});
    }

    int rem; // 删除重心后剩余连通块体积的最小值
    int cog; // 重心
    vector<bool> vis;
    void getCog() {
        vis.resize(n);
        rem = INT_MAX;
        cog = 1;
        dfsCog(1);
    }
    int dfsCog(int u) {
        vis[u] = true;
        int s = 1, res = 0;
        for (auto [w, v] : e[u]) {
            if (vis[v]) continue;
            int t = dfsCog(v);
            res = max(res, t);
            s += t;
        }
        res = max(res, n - s);
        if (res < rem) {
            rem = res;
            cog = u;
        }
        return s;
    }
};
#define int long long

void solve() {
    int n;
    cin >> n;
    vector<multiset<int>> adj(n);
    for (int i = 0; i < n; i++) {
        int u, v;
        cin >> u >> v;
        u--, v--;
        if (~u) {
            adj[i].insert(u);
            adj[u].insert(i);
        }
        if (~v) {
            adj[i].insert(v);
            adj[v].insert(i);
        }
    }
    auto dbg = adj;
    auto getCog = [&](int st) {
        // cout << st << "\n";
        // for (int i = 0; i < n; i++) {
        //     for (auto y : adj[i]) {
        //         cout << i + 1 << " " << y + 1 << "\n";
        //     }
        // }
        // cout << "\n";

        int N = 0;
        auto getSize = [&](auto self, int x, int p) -> void {
            N++;
            for (auto y : adj[x]) {
                if (y != p) {
                    self(self, y, x);
                }
            }
        };
        getSize(getSize, st, -1);

        vector<int> siz(n);
        vector<int> weight(n);

        array<int, 2> ans{-1, -1};
        auto dfs = [&](auto self, int x, int p) -> void {
            siz[x] = 1;
            weight[x] = 0;
            for (auto y : adj[x]) {
                if (y == p) continue;
                self(self, y, x);
                siz[x] += siz[y];
                weight[x] = max(weight[x], siz[y]);
            }
            weight[x] = max(weight[x], N - siz[x]);
            if (weight[x] <= N / 2) {
                ans[ans[0] != -1] = x;
            }
        };
        dfs(dfs, st, -1);

        return pair<int, vector<int>>{ans[0], siz};
    };

    auto query = [&](int x, int y) {
        cout << "? " << x + 1 << " " << y + 1 << endl;
        int t;
        cin >> t;
        return t;
    };
    auto print = [&](int x) {
        cout << "! " << x + 1 << endl;
    };

    int now = 0;
    while (1) {
        if (adj[now].size() == 0) {
            print(now);
            return;
        }
        auto [s, siz] = getCog(now);

        if (adj[s].size() == 2) {
            int s1 = *adj[s].begin();
            int s2 = *++adj[s].begin();

            int t = query(s1, s2);
            if (t == 1) {
                print(s);
                return;
            } else if (t == 0) {
                adj[s1].erase(s);
                adj[s].erase(s1);
                now = s1;
            } else {
                adj[s2].erase(s);
                adj[s].erase(s2);
                now = s2;
            }
        } else if (adj[s].size() == 3) {

            array<int, 3> arr{*adj[s].begin(), *++adj[s].begin(), *--adj[s].end()};
            // sort(arr.begin(), arr.end(), [&](int u, int v) { return siz[u] > siz[v]; });
            auto [s1, s2, s3] = arr;

            int t = query(s1, s2);
            if (t == 1) {
                adj[s].erase(s1);
                adj[s].erase(s2);
                adj[s1].erase(s);
                adj[s2].erase(s);
                now = s;
            } else if (t == 0) {
                adj[s].erase(s1);
                adj[s1].erase(s);
                now = s1;
            } else if (t == 2) {
                adj[s].erase(s2);
                adj[s2].erase(s);
                now = s2;
            }
        } else if (adj[s].size() == 1) {
            int s1 = *adj[s].begin();
            int t = query(s, s1);
            if (t == 0) {
                print(s);
            } else if (t == 2) {
                print(s1);
            } else {
                // assert(1 != 1);
                while (1) {
                }
            }
            return;
        } else {
            assert(2 != 2);
        }
    }
}

signed main() {
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
    int t = 1;
    cin >> t;
    while (t--) {
        solve();
    }
    return 0;
}

詳細信息

Test #1:

score: 100
Accepted
time: 1ms
memory: 3860kb

input:

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

output:

? 1 3
? 4 3
! 4
? 2 1
! 1

result:

ok OK (2 test cases)

Test #2:

score: -100
Time Limit Exceeded

input:

5555
8
2 0
8 6
0 0
3 0
0 0
7 0
0 0
5 4
0
0
2
8
0 0
1 4
2 0
0 0
7 8
0 0
3 0
6 0
0
1
0
8
5 8
0 0
1 7
0 0
0 0
4 2
0 0
6 0
0
0
2
5
4 5
3 1
0 0
0 0
0 0
0
2
8
0 0
0 0
5 6
0 0
1 4
2 0
3 8
0 0
0
0
5
3 0
5 1
0 0
0 0
4 0
0
2
5
5 0
0 0
0 0
3 0
2 4
1
0
3
3 0
1 0
0 0
2
2
2 0
0 0
0
3
2 3
0 0
0 0
2
10
2 8
9 7
0 0
...

output:

? 2 4
? 2 7
? 1 2
! 2
? 3 5
? 1 3
? 4 2
! 4
? 1 6
? 1 7
? 5 1
! 1
? 2 4
? 3 2
! 2
? 5 6
? 1 4
! 1
? 1 5
? 3 1
! 1
? 1 2
? 3 5
! 3
? 2 3
! 3
? 2 1
! 2
? 2 3
! 3
? 2 5
? 1 9
? 10 9
! 9
? 2 1
! 2
? 5 9
? 4 5
? 8 3
! 8
? 5 8
? 1 5
? 3 9
! 7
? 3 4
? 1 7
? 2 8
! 8
? 2 1
! 1
? 3 4
? 1 7
! 7
? 4 5
? 2 3
? 4...

result: