QOJ.ac

QOJ

IDProblemSubmitterResultTimeMemoryLanguageFile sizeSubmit timeJudge time
#757813#9570. Binary TreeEureka#RE 0ms0kbC++145.0kb2024-11-17 13:46:142024-11-17 13:46:14

Judging History

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

  • [2024-11-17 13:46:14]
  • 评测
  • 测评结果:RE
  • 用时:0ms
  • 内存:0kb
  • [2024-11-17 13:46:14]
  • 提交

answer


//
// Created by 16429 on 2024/11/17.
//
#include "bits/stdc++.h"
using namespace std;
const int N = 3e5+ 50;

struct node{
    int v,nt;
};

struct Tree{
    vector<int> head,id;
    vector<node> ed;
    int tot;
    int n;

    void init(int x){
        tot = 0;
        n = x;
        ed = vector<node>(2*(n+1),{0,0});
        id = head = vector<int>(n+1);
    }

    void add_edge(int u,int v){
        ed[++tot] = {v,head[u]};
        head[u] = tot;
    }

};

int sz[N],  // 这个节点的「大小」(所有子树上节点数 + 该节点)
weight[N],  // 这个节点的「重量」,即所有子树「大小」的最大值
centroid[2];  // 用于记录树的重心(存的是节点编号)

void GetCentroid(int cur, int fa, Tree &tre) {  // cur 表示当前节点 (current)
    sz[cur] = 1;
    weight[cur] = 0;
    for (int i = tre.head[cur]; i; i = tre.ed[i].nt) {
        if (tre.ed[i].v != fa) {  // e[i].to 表示这条有向边所通向的节点。
            GetCentroid(tre.ed[i].v, cur, tre);
            sz[cur] += sz[tre.ed[i].v];
            weight[cur] = max(weight[cur], sz[tre.ed[i].v]);
        }
    }
    weight[cur] = max(weight[cur], tre.n - sz[cur]);
    if (weight[cur] <= tre.n / 2) {  // 依照树的重心的定义统计
        centroid[centroid[0] != 0] = cur;
    }
}

int getzhong(Tree &tre){
    for (int i = 0; i <= tre.n; ++i) {
        sz[i] = weight[i] = centroid[0] = 0;
    }
    GetCentroid(1, 0, tre);
    return centroid[0];
}

int gtsz(int nw,int fa,Tree &tre){

    int res = 1;
    for(int i= tre.head[nw]; i ; i = tre.ed[i].nt){
        int v = tre.ed[i].v;
        if(v==fa)continue;
        res += gtsz(v,nw,tre);
    }
    return res;
}

void cpt(int nw,int fa,Tree &tre,Tree &t2,int &ct,int t2f){
    for(int i= tre.head[nw]; i ; i = tre.ed[i].nt){
        int v = tre.ed[i].v;
        if(v==fa)continue;
        t2.id[++ct] = tre.id[v];
        t2.add_edge(t2f,ct);
        t2.add_edge(ct,t2f);
        cpt(v,nw,tre,t2,ct,ct);
    }
}

void copyTree(Tree& t1,Tree& t2,int nw,int fa,vector<int> &bz){//吧t1的nw的子树给t2
    int sz = 1;

    auto fd = [](vector<int> &vc,int x){
        for(auto it:vc){
            if(it==x)return 1;
        }
        return 0;
    };

    for(int i= t1.head[nw]; i ; i = t1.ed[i].nt){
        int v = t1.ed[i].v;
        if(v==fa)continue;
        if(fd(bz,v))continue;
        sz += gtsz(v,nw,t1);
    }

    t2.init(sz);
    int ct = 1;
    t2.id[1] = t1.id[nw];



    for(int i= t1.head[nw]; i ; i = t1.ed[i].nt){
        int v = t1.ed[i].v;
        if(v==fa)continue;
        if(fd(bz,v))continue;
        t2.id[++ct] = t1.id[v];
        t2.add_edge(1,ct);
        t2.add_edge(ct,1);
        cpt(v,nw,t1,t2,ct,ct);
    }

}

int qe(int u,int v,Tree &tre){
    cout<<"? "<<tre.id[u]<<' '<<tre.id[v]<<endl;
    fflush(stdout);
    int res;cin>>res;
    return res;

}

int querry(Tree &tre){
    if(tre.n==1){
        return tre.id[1];
    }

//    int zx = getzhong(tre);
    int zx = 1;

    vector<int> sn;

    for(int i= tre.head[zx]; i ; i = tre.ed[i].nt){
        sn.push_back(tre.ed[i].v);
    }

    if(sn.size()==1){
        Tree t2;
        int uu = qe(zx,sn[0],tre);
        if(uu==0){
            return tre.id[zx];
        }
        vector<int> by;
        copyTree(tre,t2,sn[0],zx,by);
        return querry(t2);
    }else if(sn.size()==2){

        int uu = qe(sn[0],sn[1],tre);
        if(uu==1)return tre.id[zx];
        if(uu==2)swap(sn[0],sn[1]);
        vector<int> bz;
        Tree t2;
        copyTree(tre,t2,sn[0],zx,bz);
        return querry(t2);
    }else if(sn.size()==3){
        int uu = qe(sn[0],sn[1],tre);
        if(uu==1){
            vector<int> bz;bz.push_back(sn[1]);bz.push_back(sn[0]);
            Tree t2;
            copyTree(tre,t2,zx,0,bz);
            return querry(t2);
        }
        if(uu==0){
            vector<int> bz;
            Tree t2;
            copyTree(tre,t2,sn[0],zx,bz);
            return querry(t2);
        }
        if(uu==2){
            vector<int> bz;;
            Tree t2;
            copyTree(tre,t2,sn[1],zx,bz);
            return querry(t2);
        }
    }

}

void work(){
    int n;cin>>n;
    Tree tre;
    tre.init(n);
    for(int i = 1;  i<= n ; ++i){
        int l;cin>>l;
        if(l)tre.add_edge(i,l),tre.add_edge(l,i);
        cin>>l;
        if(l)tre.add_edge(i,l),tre.add_edge(l,i);
    }

    for(int i = 1; i <= n ;++i)tre.id[i] = i;

    int res = querry(tre);

    cout<<"! "<<res<<endl;
    fflush(stdout);

}

int main(){
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    int t;cin>>t;
    while (t--){
        work();
    }
    return 0;
}
/*
1
10
2 3
0 0
4 5
6 0
0 7
8 9
10 0
0 0
0 0
0 0
 */
/*
1
20
2 3
 4 5
 6 7
 8 9
 10 11
 12 13
 14 15
 0 0
 16 0
 0 17
 0 0
 18 0
 0 0
 0 19
 0 0
 0 0
 0 0
 0 0
 20 0
 0 0

 */

Details

Tip: Click on the bar to expand more detailed information

Test #1:

score: 0
Runtime Error

input:

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

output:

? 1 2
? 5 3
? 3 4

result: