제출 #1338026

#제출 시각아이디문제언어결과실행 시간메모리
1338026alexddSpace Thief (JOI25_thief)C++20
0 / 100
3094 ms580 KiB
#include "thief.h"
#include <bits/stdc++.h>
using namespace std;

void myassert(bool bl)
{
    if(!bl) while(1);
}

int n,m;
vector<int> u, v;
vector<int> arb[10005];

vector<int> myq;
void dfs(int nod, int par, int parid, int semn)
{
    myassert(par != -1);
    myq[parid] = ((nod == u[parid]) ^ semn);
    for(int eid:arb[nod])
    {
        if(eid == parid)
            continue;
        int adj = u[eid] + v[eid] - nod;
        dfs(adj, nod, eid, semn);
    }
}

int cine[10005];
vector<int> ord;
void dfs_ord(int nod, int par)
{
    for(int eid:arb[nod])
    {
        int adj = u[eid] + v[eid] - nod;
        if(adj == par)
            continue;
        cine[eid] = adj;
        ord.push_back(eid);
        dfs_ord(adj, nod);
    }
}

int find_node(int root, int semn, vector<int> good_children)
{
    myq.clear();
    myq.resize(m,0);
    vector<int> isgood(m, 0);
    for(int x:good_children) isgood[x] = 1;
    for(int eid:arb[root])
    {
        int adj = u[eid] + v[eid] - root;
        dfs(adj, root, eid, isgood[eid] ^ semn);
    }
    assert(query(myq));

    ord.clear();
    for(int eid:arb[root])
    {
        int adj = u[eid] + v[eid] - root;
        if(isgood[adj] ^ semn)
        {
            ord.push_back(eid);
            cine[eid] = adj;
            dfs_ord(adj, root);
        }
    }

    int st = -1, dr = ord.size() - 1, ans = -2;
    while(st <= dr)
    {
        int mij = (st + dr) / 2;

        vector<int> newq = myq;
        for(int i=0;i<ord.size();i++)
        {
            if(i <= mij)
                newq[ord[i]] = myq[ord[i]];
            else
                newq[ord[i]] = myq[ord[i]] ^ 1;
        }

        if(query(newq))
        {
            ans = mij;
            dr = mij-1;
        }
        else
        {
            st = mij+1;
        }
    }
    assert(ans != -2);

    if(ans == -1)
    {
        return root;
    }
    else
    {
        return cine[ord[ans]];
    }
}

void enter_endgame(int root, vector<int> good_children)
{
    int A = find_node(root, 0, good_children);

    vector<bool> isgood(m, 0);
    for(int x:good_children)
        isgood[x] = 1;
    good_children.clear();
    for(int x:arb[root])
        if(!isgood[x])
            good_children.push_back(x);

    int B = find_node(root, 1, good_children);

    //cerr<<A<<" "<<B<<" my answer\n";
    answer(A, B);
}

bool iss[10005];

int siz[10005];
void get_sizes(int nod, int par)
{
    siz[nod] = 1;
    for(int eid:arb[nod])
    {
        int adj = u[eid] + v[eid] - nod;
        if(adj == par || iss[adj])
            continue;
        get_sizes(adj, nod);
        siz[nod] += siz[adj];
    }
}
int get_centroid(int nod, int par, int tot)
{
    for(int eid:arb[nod])
    {
        int adj = u[eid] + v[eid] - nod;
        if(adj == par || iss[adj])
            continue;
        if(siz[adj]*2 > tot)
            return get_centroid(adj, nod, tot);
    }
    return nod;
}

void solve_abore()
{



    vector<vector<int>> cens(10005);
    cens[0].push_back(0);

    for(int d=0;;d++)
    {
        if(cens[d].empty())
            break;
        //cerr<<d<<" d\n";
        int maxsiz = 0;
        for(int&nod:cens[d])
        {
            get_sizes(nod, -1);
            nod = get_centroid(nod, -1, siz[nod]);
            iss[nod] = 1;

            int cntc = 0;
            for(int eid:arb[nod])
            {
                int adj = u[eid] + v[eid] - nod;
                if(!iss[adj])
                {
                    cens[d+1].push_back(adj);
                    cntc++;
                }
            }
            maxsiz = max(maxsiz, cntc);
        }
        //cerr<<"got centroids\n";

        //check if nod is one of the special nodes------------------------------
        int b = 0;
        while((1<<b) < maxsiz)
            b++;
        for(;b>=0;b--)
        {
            //cerr<<b<<" start b\n";
            vector<int> aux(m, 0);
            for(int nod:cens[d])
            {
                vector<pair<int,int>> chs;
                for(int eid:arb[nod])
                {
                    int adj = u[eid] + v[eid] - nod;
                    if(!iss[adj])
                        chs.push_back({adj, eid});
                }
                for(int poz=0;poz<chs.size();poz++)
                {
                    if((1<<b)&poz)
                    {
                        aux[chs[poz].second] = (nod == u[chs[poz].second]);
                    }
                    else
                    {
                        aux[chs[poz].second] = (nod != u[chs[poz].second]);
                    }
                }
            }

            vector<int> q[2];
            for(int i=0;i<m;i++)
            {
                q[0].push_back(aux[i]);
                q[1].push_back(aux[i] ^ 1);
            }

            for(int semn=0;semn<2;semn++)
            {
                if(query(q[semn]))
                {
                    //do a binary search to find what node this is about and then enter endgame

                    //cerr<<"started binsearch\n";
                    int st = 0, dr = cens[d].size() - 1, ans = -1;
                    while(st <= dr)
                    {
                        int mij = (st + dr) / 2;

                        vector<int> newq(m,0);
                        for(int i=0;i<cens[d].size();i++)
                        {
                            int nod = cens[d][i];
                            if(i <= mij)
                            {
                                for(int eid:arb[nod])
                                    newq[eid] = q[semn][eid];
                            }
                            else
                            {
                                for(int eid:arb[nod])
                                    newq[eid] = (q[semn][eid] ^ 1);
                            }
                        }

                        if(query(newq))
                        {
                            ans = mij;
                            dr = mij-1;
                        }
                        else
                        {
                            st = mij+1;
                        }
                    }
                    myassert(ans != -1);
                    //cerr<<"ended binsearch\n";


                    int root = cens[d][ans];
                    vector<int> good_children;
                    int poz = 0;
                    for(int eid:arb[root])
                    {
                        int adj = u[eid] + v[eid] - root;
                        if(!iss[adj])
                        {
                            if((((1<<b)&poz) == 0) == semn)
                            {
                                good_children.push_back(eid);
                            }
                            poz++;
                        }
                    }
                    //cerr<<"got to endgame\n";
                    enter_endgame(root, good_children);
                    return;
                }
            }
        }

    }

}
void solve(int N, int M, std::vector<int> U, std::vector<int> V)
{
    myassert(M == N-1);
    n = N;
    m = M;
    u = U;
    v = V;
    for(int i=0;i<m;i++)
    {
        arb[u[i]].push_back(i);
        arb[v[i]].push_back(i);
    }
    solve_abore();
}
/*

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

*/
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...