QOJ.ac

QOJ

ID题目提交者结果用时内存语言文件大小提交时间测评时间
#753312#9570. Binary TreekalikariWA 4ms3900kbC++174.1kb2024-11-16 12:19:242024-11-16 12:19:25

Judging History

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

  • [2024-11-16 12:19:25]
  • 评测
  • 测评结果:WA
  • 用时:4ms
  • 内存:3900kb
  • [2024-11-16 12:19:24]
  • 提交

answer

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

// 读取输入函数,用于快速读取整数
int Read() {
    int x = 0;
    char ch = getchar();
    bool f = 0;
    while (ch < '0' || ch > '9') {
        if (ch == '-') f = 1, ch = getchar();
        else if (ch == EOF) return 0;
        else ch = getchar();
    }
    while (ch >= '0' && ch <= '9') x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
    return f ? -x : x;
}

// 全局变量定义
int fa[100005], l[100005], r[100005]; // fa:父节点,l:左子节点,r:右子节点
int root; // 树的根节点
int siz[100005]; // 子树大小
int n; // 当前节点个数
bool flag; // 标记是否找到重心

// 深度优先搜索,计算子树大小并找到重心
void dfs(int x) {
    siz[x] = 1; // 初始化子树大小为1
    // 递归处理左子树
    if (l[x]) {
        dfs(l[x]);
        siz[x] += siz[l[x]];
    }
    // 递归处理右子树
    if (r[x]) {
        dfs(r[x]);
        siz[x] += siz[r[x]];
    }
    // 如果已经找到重心,直接返回
    if (flag) return;

    // 检查是否满足重心条件
    // 重心条件:去掉当前节点后,剩余连通块大小 <= n / 2
    if (siz[l[x]] <= n / 2 && siz[r[x]] <= n / 2 && n - siz[x] + 1 <= n / 2 && l[x] && r[x]) {
        flag = 1; // 找到重心
        // 查询左右子节点,询问哪个更接近特殊节点
        printf("? %d %d\n", l[x], r[x]);
        fflush(stdout);
        int op = Read();
        // 根据交互器返回的结果进行处理
        if (op == 1) l[x] = 0, r[x] = 0, n = n - siz[x] + 1; // 相等情况,删除左右子节点
        if (op == 2) root = r[x], n = siz[r[x]], fa[r[x]] = 0; // 右子节点更近,更新根节点为右子节点
        if (op == 0) root = l[x], n = siz[l[x]], fa[l[x]] = 0; // 左子节点更近,更新根节点为左子节点
        return;
    }

    // 检查父节点和左子节点的情况
    if (siz[l[x]] <= n / 2 && siz[r[x]] + 1 <= n / 2 && n - siz[x] <= n / 2 && fa[x] && l[x]) {
        flag = 1;
        printf("? %d %d\n", l[x], fa[x]);
        fflush(stdout);
        int op = Read();
        if (op == 1) l[x] = 0, fa[x] = 0, root = x, n = siz[r[x]] + 1; // 相等情况,删除左子节点和父节点
        if (op == 2) {
            n = n - siz[x];
            if (l[fa[x]] == x) l[fa[x]] = 0;
            if (r[fa[x]] == x) r[fa[x]] = 0;
        }
        if (op == 0) root = l[x], n = siz[l[x]], fa[l[x]] = 0;
        return;
    }

    // 检查父节点和右子节点的情况
    if (siz[l[x]] + 1 <= n / 2 && siz[r[x]] <= n / 2 && n - siz[x] <= n / 2 && fa[x] && r[x]) {
        flag = 1;
        printf("? %d %d\n", r[x], fa[x]);
        fflush(stdout);
        int op = Read();
        if (op == 1) r[x] = 0, fa[x] = 0, root = x, n = siz[l[x]] + 1;
        if (op == 2) {
            n = n - siz[x];
            if (l[fa[x]] == x) l[fa[x]] = 0;
            if (r[fa[x]] == x) r[fa[x]] = 0;
        }
        if (op == 0) root = r[x], n = siz[r[x]], fa[r[x]] = 0;
        return;
    }
    return;
}

signed main() {
    int T = Read(); // 读取测试用例数量
    while (T--) {
        n = Read(); // 读取节点数量
        // 初始化
        for (int i = 1; i <= n; i++) fa[i] = 0;
        for (int i = 1; i <= n; i++) {
            l[i] = Read(), r[i] = Read();
            if (l[i]) fa[l[i]] = i;
            if (r[i]) fa[r[i]] = i;
        }
        // 找到根节点
        for (int i = 1; i <= n; i++) if (!fa[i]) root = i;

        // 使用 DFS 找重心
        if (n > 2) {
            flag = 0;
            dfs(root);
        }

        // 当 n == 1 时,直接输出根节点
        if (n == 1) {
            printf("! %d\n", root);
            fflush(stdout);
        } else {
            // 当 n == 2 时,询问根节点和其子节点
            printf("? %d %d\n", root, l[root] ? l[root] : r[root]);
            fflush(stdout);
            int op = Read();
            printf("! %d\n", op == 0 ? root : (l[root] ? l[root] : r[root]));
            fflush(stdout);
        }
    }
    return 0;
}

详细

Test #1:

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

input:

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

output:

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

result:

ok OK (2 test cases)

Test #2:

score: -100
Wrong Answer
time: 4ms
memory: 3776kb

input:

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

output:

? 5 2
? 1 2
! 2

result:

wrong answer There are 3 candidates. (test case 1)