Cod sursa(job #2344269)

Utilizator BogdanisarBurcea Bogdan Madalin Bogdanisar Data 14 februarie 2019 21:57:48
Problema Stramosi Scor 80
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.13 kb
#include <bits/stdc++.h>

using namespace std;

#if 1
    #define pv(x) std::cerr<<#x<<" = "<<(x)<<"; ";std::cerr.flush()
    #define pn std::cerr<<std::endl
#else
    #define pv(x)
    #define pn
#endif

#ifdef INFOARENA
    ifstream in("stramosi.in");
    ofstream out("stramosi.out");
#else
    #define in cin
    #define out cout
#endif

using ll = long long;
using ull = unsigned long long;
using uint = unsigned int;
using ld = long double;
using pii = pair<int,int>;
using pll = pair<ll,ll>;
using pld = pair<ld, ld>;
#define pb push_back
const double PI = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862;
const int inf_int = 1e9 + 5;
const ll inf_ll = 1e18 + 5;
const int NMax = 25e4 + 5;
const int dx[] = {-1,0,0,+1}, dy[] = {0,-1,+1,0};
const double EPS = 1e-8;

// rezolvare prin tehnica small to large / dsu on tree;


int depth[NMax], ans[NMax], sub[NMax];
set<int> queryForDepth[NMax];
vector<int> adj[NMax];
vector<pii> query[NMax];
// depth[i] = adancimea nodului i;
// ans[i] = raspunsul pentru al i-lea query;
// sub[i] = numarul de noduri in subarborele nodului i;
// queryForDepth[d] = un set de indici al acelor query-uri inregistrate la momentul curent care cer un stramos pe depth-ul d;
// adj[i] = lista de adiacenta pentru nodului i;
// query[i] = o lista de (AncestorDepth, QueryIndex) asociate nodului i;

void getSub(int node) {
    sub[node] = 1;
    for (int nxt : adj[node]) {
        getSub(nxt);
        sub[node] += sub[nxt];
    }
}



void add(int node, int heavy, bool isAdd) {
    if (isAdd) {
        for (pii p : query[node]) {
            int dep = p.first;
            int idx = p.second;
            queryForDepth[dep].insert(idx);
        }
    }
    else {
        for (pii p : query[node]) {
            int dep = p.first;
            int idx = p.second;
            queryForDepth[dep].erase(idx);
        }
    }

    for (int nxt : adj[node]) {
        if (nxt == heavy) {
            continue;
        }

        add(nxt, heavy, isAdd);
    }
}

void dfs(int node, bool keep) {
    int heavy = -1, maxSub = 0;
    for (int nxt : adj[node]) {
        if (maxSub < sub[nxt]) {
            maxSub = sub[nxt];
            heavy = nxt;
        }
    }

    for (int nxt : adj[node]) {
        if (nxt == heavy) {
            continue;
        }

        dfs(nxt, false);
    }

    if (heavy != -1) {
        dfs(heavy, true);
    }

    add(node, heavy, true);

    for (auto idx : queryForDepth[depth[node]]) {
        ans[idx] = node;
    }

    if (keep == 0) {
        add(node, -1, false);
    }    
}

int main() {
    cin.sync_with_stdio(false);
    cin.tie(0);

    int N,M;
    in >> N >> M;
    for (int i = 1; i <= N; ++i) {
        int dad;
        in >> dad;
        adj[dad].pb(i);
        depth[i] = depth[dad] + 1;
    }

    for (int i = 1; i <= M; ++i) {
        int node,pth;
        in >> node >> pth;
        int pdepth = depth[node] - pth;
        if (pdepth <= 0) {
            ans[i] = 0;
        }
        else {
            query[node].pb({pdepth, i});
        }
    }

    getSub(0);
    dfs(0, false);

    for (int i = 1; i <= M; ++i) {
        out << ans[i] << '\n';
    }

    return 0;
}