QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#748021#9570. Binary Treeucup-team1113WA 1ms3688kbC++204.7kb2024-11-14 19:04:122024-11-14 19:04:12

Judging History

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

  • [2024-11-14 19:04:12]
  • 评测
  • 测评结果:WA
  • 用时:1ms
  • 内存:3688kb
  • [2024-11-14 19:04:12]
  • 提交

answer

//关注不变量
//多次查询可以思考根号分治
//位运算有关多想拆位
//字符串多想hash
//对字符串频繁操作可以映射成整数
//点的限制加到边上
#include<bits/stdc++.h>
using namespace std;
mt19937_64 rnd(chrono::steady_clock::now().time_since_epoch().count());
typedef long long LL;
typedef unsigned long long ULL;
typedef pair<int,int> PII;
typedef __int128 i128;
const int INF = 0x3f3f3f3f;
const int N = 4e5 + 10, mod = 1e9 + 7;



int numm = 0;
void solve() {
    int n;
    cin >> n;
    numm++;
    string s = to_string(n);
    vector<set<int>> g(n + 1);  //存图
    for (int i = 1; i <= n; i++) {
        int x, y;
        cin >> x >> y;
        s = s + "#" + to_string(x) + "U" + to_string(y);
        if (x) {
            g[x].insert(i);
            g[i].insert(x);
        }
        if (y) {
            g[y].insert(i);
            g[i].insert(y);
        }
    }

    if(numm == 219) {
        cout << s << '\n';
        exit(0);
    }
    vector<int> sz(n + 1, 0), father(n + 1, 0); //每个点子树的sz,和父亲
    int root = 1;
    auto get_sz = [&](auto get_sz, int u, int fa) -> void { //搜sz
        sz[u] = 1;
        father[u] = fa;
        for (auto v : g[u]) {
            if (v == fa) continue;
            get_sz(get_sz, v, u);
            sz[u] += sz[v];
        }
    };
    int aim = root, aimval = 1e8;  //重心
    auto get_mid = [&](auto get_mid, int u, int fa) -> void { //求重心
        int mx = 0;
        for (auto v : g[u]) {
            if (v == fa) continue;
            get_mid(get_mid, v, u);
            mx = max(mx, sz[v]);
        }
        mx = max(sz[root] - sz[u], mx);
        if (mx < aimval) {
            aim = u;
            aimval = mx;
        }
    };

    int tot = 0;
    auto query = [&](int u, int v) -> int {
        tot++;
        if((1ll << tot) > n) {
            cout << "WAA\n";
            exit(0);
        }
        assert((1ll << tot) <= n);
        cout << "? " << u << ' ' << v << endl;
        int res;
        cin >> res;
        return res;
    };

    while (1) {
        get_sz(get_sz, root, 0);
        aim = root, aimval = 1e8;
        get_mid(get_mid, root, 0);
        if (g[aim].size() == 0) {   //一个点
            cout << "! " << aim << endl;
            return;
        }
        else if (g[aim].size() == 1) { //全图只有两个点
            int u;
            for (auto v : g[aim]) u = v;
            auto res = query(aim, u);
            if (res == 0) cout << "! " << aim << endl;
            else cout << "! " << u << endl;
            return;
        }
        else if (g[aim].size() == 2) { //询问两边的点
            int u, v;
            int num = 0;
            for (auto k : g[aim]) {
                if (!num) u = k;
                else v = k;
                num++;
            }
            auto res = query(u, v);
            if (res == 0) {
                g[u].erase(aim);
                g[aim].erase(u);
                root = u;
            }
            else if (res == 1) {
                cout << "! " << aim << endl;
                return;
            }
            else {
                g[v].erase(aim);
                g[aim].erase(v);
                root = v;
            }
        }
        else {  //询问最大的两个邻居上的点
            int aim1 = 0, aim2 = 0, num = 0;
            for (auto v : g[aim]) {
                if (v == father[aim]) continue;
                num++;
                if (num == 1) aim1 = v;  //第一个邻居
                else aim2 = v; //第二个邻居
            }
            int fa = father[aim]; //父亲
            vector<PII> s(3);
            s[0] = {sz[aim1], aim1};
            s[1] = {sz[aim2], aim2};
            s[2] = {sz[root] - sz[aim], fa};
            sort(s.begin(), s.end(), [&](PII a, PII b) {
                return a.first > b.first;
            });
            int u = s[0].second, v = s[1].second;
            auto res = query(u, v);
            if (res == 0) {
                g[u].erase(aim);
                g[aim].erase(u);
                root = u;
            }
            else if (res == 1) {
                g[aim].erase(u);
                g[u].erase(aim);
                g[aim].erase(v);
                g[v].erase(aim);
                root = aim;
            }   
            else {
                g[v].erase(aim);
                g[aim].erase(v);
                root = v;
            }
        }
    }
}

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

Details

Tip: Click on the bar to expand more detailed information

Test #1:

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

input:

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

output:

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

result:

ok OK (2 test cases)

Test #2:

score: -100
Wrong Answer
time: 1ms
memory: 3564kb

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
0
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 4
? 3 2
! 3
? 1 6
? 1 7
? 5 1
! 1
? 2 5
? 3 2
! 2
? 5 6
? 1 4
! 1
? 1 5
? 3 1
! 1
? 4 2
? 3 4
! 3
? 2 3
! 3
? 2 1
! 2
? 2 3
! 3
? 2 6
? 1 9
? 10 9
! 9
? 2 1
! 2
? 5 9
? 4 8
? 5 3
! 5
? 5 8
? 7 1
? 5 3
! 5
? 9 3
? 1 7
? 9 2
! 9
? 2 1
! 1
? 4 3
? 1 7
! 7
? 4 5
? 2 3
? 4...

result:

wrong answer Token parameter [name=op] equals to "7#7U6#0U0#0U0#1U0#0U0#3U2#5U0", doesn't correspond to pattern "[?!]{1,1}" (test case 219)