QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#757975#9570. Binary Treepiaoyun#ML 2ms5876kbC++143.4kb2024-11-17 14:56:482024-11-17 14:56:49

Judging History

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

  • [2024-11-17 14:56:49]
  • 评测
  • 测评结果:ML
  • 用时:2ms
  • 内存:5876kb
  • [2024-11-17 14:56:48]
  • 提交

answer

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

int query(int x, int y){
    cout << "? " << x << " " << y << endl;
    cout.flush();
    cin >> x;
    return x;
}

vector<int> adj[100005];
bool vis[100005];
int T,n;
int sz;

void add(int x, int y){
    // cout << "add " << x << " " << y << endl;
    adj[x].push_back(y);
    adj[y].push_back(x);
}

void Free(int x, int fa){
    if(!vis[x]) sz --;
    vis[x] = true;
    for(int y: adj[x]){
        if(y == fa) continue;
        Free(y, x);
    }
}

int mn,centre = 0;
int sum[100005];
int tot = 0;
int father[100005];

void dfs(int u,int fa){
    // cout << "123\n";
    father[u] = fa;
    if(vis[u]){
        sum[u] = 0;
        return;
    }
    sum[u] = 1;
    for(auto v : adj[u]){
        if(v == fa) continue;
        dfs(v,u);
        sum[u] += sum[v];
    }
}

void get_centre(int u,int fa){
    int mx = 0;
    for(auto v : adj[u]){
        if(v == fa) continue;
        get_centre(v,u);
        mx = max(mx, sum[v]);
    }
    if(u != fa){
        mx = max(mx , tot - sum[u]);
    }
    // cout << u << " " << mx << endl;
    if(mx < mn){
        mn = mx;
        centre = u;
    }
}


int Find(int S){
    // cout << "haha\n";
    mn = 1e9;
    dfs(S,S);
    tot = sum[S];
    get_centre(S,S);
    // cout << centre << " " << mn << endl;
    return centre;
}

vector<int> get_adj(int x){
    vector<int> ret;
    for(int i: adj[x]){
        if(!vis[i]) ret.push_back(i);
    }
    // for(int x: ret) cout << x << "#";
    return ret;
}

int main(){
    cin >> T;
    while(T--){
        cin >> n;
        for(int i=1;i<=n;i++) vis[i] = false;
        for(int i=1;i<=n;i++) adj[i].clear();
        for(int i=1;i<=n;i++){
            int l,r;
            cin >> l >> r;
            if(l) add(i, l);
            if(r) add(i, r);
        }

        sz = n;
        while(sz > 3){
            int alive = -1;
            for(int i=1;i<=n;i++) 
            if(!vis[i]){
                alive = i;
                break;
            }

            int x = Find(alive);
            vector<int> v = get_adj(x);
            
            assert(v.size() >= 2);
            int a = v[0], b = v[1];
            int res = query(a, b);

            if(res == 0){
                Free(b, x);
            }
            else if(res == 1){
                Free(b, x);
                Free(a, x);
            }
            else{
                // res = 2
                Free(a, x);
            }
        }

        int ans = -1;
        vector<int> v;
        for(int i=1;i<=n;i++) if(!vis[i]) v.push_back(i);

        if(v.size() == 1){
            ans = v[0];
        }
        else if(v.size() == 2){
            int x = v[0], y = v[1];
            int res = query(x,y);
            if(res == 0) ans = x;
            else ans = y;
        }
        else if(v.size() == 3){
            int x = v[0], y = v[1];
            int mid = Find(x);
            x = y = -1;
            for(int i: v){
                if(i != mid){
                    if(x == -1) x = i;
                    else y = i;
                }
            }

            int res = query(x,y);
            if(res == 0) ans = x;
            else if(res == 1) ans = mid;
            else ans = y;
        }

        cout << "! " << ans << endl;
        cout.flush();
    }
}

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 100
Accepted
time: 2ms
memory: 5876kb

input:

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

output:

? 1 5
? 2 4
! 3
? 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
0
1
1

output:

? 2 5
? 1 8
? 2 7
! 4

result: