Submission #478803

#TimeUsernameProblemLanguageResultExecution timeMemory
478803blueThrough Another Maze Darkly (CCO21_day1problem3)C++17
25 / 25
7849 ms864880 KiB
#include <iostream>
#include <vector>
#include <deque>
#include <algorithm>
using namespace std;

const int maxN = 800'000;
const int maxQ = 800'000;

deque<int> edge[1+maxN];
vector<int> parent(1+maxN, 0);
vector<int> init_arrow(1+maxN);

vector<int> euler;
vector<int> first_dfs;
vector<bool> visit(1+maxN, 0);

void dfs1(int u)
{
    for(int v: edge[u])
    {
        if(visit[v]) continue;
        visit[v] = 1;

        parent[v] = u;
        // cerr << "parent " << v << " = " << parent[v] << '\n';
        dfs1(v);
    }
}


void dfs2(int u)
{
    // cerr << "first dfs " << u << ' ' << e << '\n';
    for(int v: edge[u])
    {
        // cerr << u << " -> " << v << '\n';
        // cerr << (v == )
        // if(v == init_arrow[u]) new_dfs = 0;
        if(v == parent[u]) continue;

        euler.push_back(v);
        dfs2(v);
        euler.push_back(u);
    }
}


int euler_ct = -1;
void dfs3(int u, int e)
{
    int new_dfs = 1;
    for(int v: edge[u])
    {
        if(v == init_arrow[u]) new_dfs = 0;
        if(v == parent[u]) continue;

        first_dfs.push_back(e + new_dfs);
        dfs3(v, e + new_dfs);
        first_dfs.push_back(e + new_dfs);
    }
}




struct query
{
    long long K;
    int i;
};

bool operator < (query A, query B)
{
    return A.K < B.K;
}

vector<int> answer(maxQ, -1);



struct segtree //add +1, count the number of +1s in a given region.
{
    int l;
    int r;

    int sm = 0;

    segtree* left = NULL;
    segtree* right = NULL;

    segtree()
    {
        ;
    }

    segtree(int L, int R)
    {
        l = L;
        r = R;
        if(l == r) return;
        int m = (l+r)/2;
        left = new segtree(l, m);
        right = new segtree(m+1, r);
    }

    void enable(int I)
    {
        if(l == r) sm = 1;
        else
        {
            if(I <= (l+r)/2)
                left->enable(I);
            else
                right->enable(I);

            sm = left->sm + right->sm;
        }
    }

    int rangesum(int L, int R)
    {
        if(R < l || r < L) return 0;
        else if(L <= l && r <= R) return sm;
        else return left->rangesum(L, R) + right->rangesum(L, R);
    }
};


int main()
{
    int N, Q;
    cin >> N >> Q;

    for(int i = 1; i <= N; i++)
    {
        int ct;
        cin >> ct;

        for(int e = 1; e <= ct; e++)
        {
            int c;
            cin >> c;
            edge[i].push_back(c);
        }
        edge[i].push_back(edge[i].front());
        edge[i].pop_front();           //The arrows are rotated, so now we move and THEN the arrow moves.
        init_arrow[i] = edge[i][0];    //The first move we make!!!
        // cerr << "init arrow " << i << " = " << init_arrow[i] << '\n';
    }

    visit[1] = 1;
    // cerr << "parent " << 1 << " = " << parent[1] << '\n';
    dfs1(1);

    for(int i = 2; i <= N; i++)
    {
        while(edge[i].back() != parent[i])
        {
            edge[i].push_back(edge[i].front());
            edge[i].pop_front();
        }
    }
    // cerr << "check\n";
    //
    // for(int i = 1; i <= N; i++)
    // {
    //     // cerr << "i = " << i << '\n';
    //     for(int j: edge[i]) cerr << j << ' ';
    //     cerr << '\n';
    // }

    dfs2(1);

    dfs3(1, 1);


    // for(int i = 0; i < 2*(N-1); i++) cerr << euler[i] << ' ';
    // cerr << '\n';
    // for(int i = 0; i < 2*(N-1); i++) cerr << first_dfs[i] << ' ';
    // cerr << '\n';

    vector<int> first_list[1+N];
    // for(int p = 0; p < 2*(N-1); p++)
    //     first_list[ first_dfs[p] ].push_back(p);

    for(int i = 0; i < 2*(N-1); i++)
        first_list[ first_dfs[i] ].push_back(i);

    deque<query> queries;
    for(int q = 0; q < Q; q++)
    {
        long long K;
        cin >> K;

        queries.push_back(query{K, q});
    }
    // cerr << "queries are: \n";
    // for(query t: queries) cerr << t.K << ' ' << t.i << '\n';
    sort(queries.begin(), queries.end());


    segtree S(0, 2*(N-1));

    long long prev_moves = 0;

    for(int d = 1; d <= N; d++)
    {
        // cerr << "\n\n";
        // cerr << "dfs index = " << d << '\n';
        int ct = 0;
        for(int f: first_list[d])
        {
            S.enable(f);
            ct++;
            // cerr << "f = " << f << '\n';

            // cerr << queries[0].K << ' ' << prev_moves << ' ' << S.rangesum(0, f) << '\n';

            while(!queries.empty() && queries[0].K <= prev_moves + S.rangesum(0, f))
            {
                int lo = 0;
                int hi = f;
                while(lo != hi)
                {
                    int mid = (lo+hi)/2;
                    if(queries[0].K <= prev_moves + S.rangesum(0, mid))
                        hi = mid;
                    else
                        lo = mid+1;
                }
                // cerr << "answering " << queries[0].i << " as " << euler[lo] << '\n';
                answer[queries[0].i] = euler[lo];
                queries.pop_front();
            }
        }
        while(!queries.empty() && queries[0].K <= prev_moves + S.rangesum(0, 2*(N-1)))
        {
            int lo = 0;
            int hi = 2*(N-1);
            while(lo != hi)
            {
                int mid = (lo+hi)/2;
                if(queries[0].K <= prev_moves + S.rangesum(0, mid))
                    hi = mid;
                else
                    lo = mid+1;
            }
            // cerr << "answering " << queries[0].i << " as " << euler[lo] << '\n';
            answer[queries[0].i] = euler[lo];
            queries.pop_front();
        }
        // cerr << curr_sum << '\n';
        // cerr << queries[0].K << ' ' << queries[0].i << '\n';


        prev_moves += S.rangesum(0, 2*(N-1));
    }
    // cerr << "part 2\n";
    long long period = 2*(N-1);

    while(!queries.empty())
    {
        int q = queries[0].i;
        long long K = queries[0].K;
        queries.pop_front();

        K = (K - prev_moves - 1 +  period*(5 * N)) % period;
        // cerr << "K mod = " << K << '\n';
        answer[q] = euler[K];
        // cerr << "answering " << q << " as " << euler[K] << '\n';
    }

    for(int q = 0; q < Q; q++)
    {
        cout << answer[q] << '\n';
    }
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...