Cod sursa(job #2836992)

Utilizator Stefan_DomuncoStefan Domunco Stefan_Domunco Data 21 ianuarie 2022 13:31:54
Problema Atac Scor 100
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.43 kb
#include <bits/stdc++.h>

using namespace std;

ifstream fin("atac.in");
ofstream fout("atac.out");

const int NMAX = 32e3 + 5, MMAX = 5e5 + 4;

int A, B, C, D, x, y;
int n, q, p, depth[NMAX];
int peuler[2 * NMAX + 5], nrpeuler = 0;
int rmq[2 * NMAX + 5][22], firstPos[NMAX];
int ans[MMAX], treeRMQ[NMAX][22];//treeRMQ[node][j] retin muchia minima pt nodes[node][j]
int father[NMAX], nodes[NMAX][22];//nodes[node][j] retin nodul cu 1 << j pozitii mai sus

vector <int> g[NMAX];
map < pair <int, int>, int > costMuchii;
bitset <NMAX> viz;

inline void citire()
{
    memset(firstPos, 0, sizeof(firstPos));
    memset(peuler, 0, sizeof(peuler));

    fin >> n >> q >> p;
    for(int i = 2; i <= n; ++i)
    {
        fin >> x >> y;
        costMuchii[{min(x, i), max(x, i)}] = y;
        g[i].push_back(x);
        g[x].push_back(i);
        father[i] = x;
    }

    fin >> x >> y >> A >> B >> C >> D;
}

inline int newX(int X, int Y)
{
    return (X * A + Y * B) % n + 1;
}

inline int newY(int Y, int Z)
{
    return (Y * C + Z * D) % n + 1;
}

void DFS(int node, int dp)
{
    if(firstPos[node] == 0)
        firstPos[node] = nrpeuler + 1;

    if(depth[node] == 0)
        depth[node] = dp;

    viz[node] = 1;
    peuler[++nrpeuler] = node;

    for(auto &it: g[node])
    {
        if(viz[it] == 1)
            continue;

        //peuler[++nrpeuler] = costMuchii[{min(node, it), max(node, it)}];
        DFS(it, dp + 1);
        peuler[++nrpeuler] = node;
    }

    //peuler[++nrpeuler] = costMuchii[aa];
}

inline void build_rmq()
{
    int i, j;

    for(i = 1; i <= nrpeuler; ++i)
        rmq[i][0] = peuler[i];

    for(j = 1; 1 << j <= nrpeuler; ++j)
    {
        for(i = 1; i + (1 << j) - 1 <= nrpeuler; ++i)
        {
            if(depth[rmq[i][j-1]] < depth[rmq[i + (1 << (j-1))][j-1]])
                rmq[i][j] = rmq[i][j-1];
            else rmq[i][j] = rmq[i + (1 << (j-1))][j-1];
        }

    }
}

inline void build_treeRMQ()
{
    int i, j;
    for(i = 1; i <= n; ++i)
        nodes[i][0] = father[i], treeRMQ[i][0] = costMuchii[{min(i, father[i]), max(i, father[i])}];

    for(j = 1; 1 << j <= n; ++j)
    {
        for(i = 2; i <= n; ++i)
        {
            if(depth[i] - (1 << j) + 1 < 1)
            {
                //nodes[i][j] = -1;
                continue;
            }

            //treeRMQ[i][j] = min(treeRMQ[i][j-1], treeRMQ[nodes[i][j-1]][j-1]);
            nodes[i][j] = nodes[ nodes[i][j-1] ][j-1];
            treeRMQ[i][j] = min(treeRMQ[i][j-1], treeRMQ[ nodes[i][j-1] ][j-1]);
        }
    }
}

inline int LCA()
{
    int xx, yy;
    xx = x;
    yy = y;

    if(firstPos[xx] > firstPos[yy])
        swap(xx, yy);

    int lung = log2(firstPos[yy] - firstPos[xx] + 1);

    if(depth[rmq[firstPos[xx]][lung]] < depth[rmq[firstPos[yy] - (1 << lung) + 1][lung]])
        return rmq[firstPos[xx]][lung];

    return rmq[firstPos[yy] - (1 << lung) + 1][lung];
}

inline int toLca(int x, int lca)
{
    int dist = depth[x] - depth[lca];
    int sol = INT_MAX, ax;

    while(dist)
    {
        ax = log2(dist);
        sol = min(sol, treeRMQ[x][ax]);
        dist -= 1 << ax;
        x = nodes[x][ax];
    }

    return sol;
}

int main()
{
    citire();
    costMuchii[{0, 0}] = 0;
    DFS(1, 1);
    build_rmq();
    build_treeRMQ();

//    for(int j = 0; 1 << j <= n; ++j)
//    {
//        fout << j << '\n';
//        for(int i = 1; i <= n; ++i)
//        {
//            fout << i << ' ' << nodes[i][j] << ' ' << treeRMQ[i][j] << '\n';
//        }
//        fout << '\n';
//    }


    int xx, yy, i, lca, currentAns, qq = q;
    i = 0;


    while(q)
    {
        --q;
        xx = x;
        yy = y;

        if(x == y)
        {
            ans[++i] = 0;
            x = newX(xx, yy);
            y = newY(yy, ans[i]);
            continue ;
        }

        lca = LCA();
        currentAns = min(toLca(x, lca), toLca(y, lca));
        ans[++i] = currentAns;

        x = newX(xx, yy);
        y = newY(yy, ans[i]);
    }

    for(i = qq - p + 1; i <= qq; ++i)
        fout << ans[i] << '\n';

//    for(int j = 0; 1 << j <= nrpeuler; ++j)
//    {
//        for(int i = 1; i + (1 << j) - 1 <= nrpeuler; ++i)
//            fout << rmq[i][j] << ' ';
//        fout << '\n';
//    }

//    for(int i = 1; i <= nrpeuler; ++i)
//        fout << peuler[i] << ' ';

    return 0;
}