/* TASK: tree LANG: C++ FROM: CodeIT Round6 IDEA: solve task offline; store some information about the levels in a Fenwick tree, compare the information before and after visiting the node in a DFS. NOTES: - AUTHOR: Yasen Trifonov */ #include #include #include #include #define MAXN (1 << 19) using namespace std; struct node { int first, second; int idx; node() {} node(int f, int s, int i) : first(f), second(s), idx(i) {} }; int n, q; int par[MAXN]; int lvl[MAXN]; vector vec[MAXN], ans[MAXN]; vector< node > queries[MAXN]; int it[MAXN]; inline void update(int pos) { assert(pos > 0); for (; pos < MAXN; pos += pos & (-pos)) it[pos] ++; } inline int query(int pos) { assert(pos >= 0); if (pos >= MAXN) pos = MAXN-1; int ans = 0; for (; pos; pos = pos & (pos-1)) ans += it[pos]; return ans; } inline int Query(int from, int to, int lv) { //printf("into query for: %d %d %d\n", from, to, lv); if (to <= 0) return 0; int ans = query(to+lv) - query( max(lv, from+lv-1) ); return ans; } inline int add(int from, int to, int lv) { if (to <= 0) { if (lv+to <= 0) return 0; // out of range int left = 0, right = 0; right = lv+to; left = max(0, lv+from-1); return right - left; } int ans = 0; if (from <= 0) { ans += min(-from+1, lv); return ans; } return ans; } void dfs(int cur) { if (par[cur] != -1) lvl[cur] = lvl[ par[cur] ] + 1; else lvl[cur] = 1; update(lvl[cur]); //printf("updating .. %d\n", lvl[cur]); int sz = (int) queries[cur].size(); ans[cur].resize(sz); for (int i=0; i < sz; ++i) { ans[cur][i] = Query(queries[cur][i].first, queries[cur][i].second, lvl[cur]); //printf("found %d\n", ans[cur][i]); } for (int i=0; i < (int)vec[cur].size(); ++i) dfs( vec[cur][i] ); for (int i=0; i < sz; ++i) { int now = Query(queries[cur][i].first, queries[cur][i].second, lvl[cur]); ans[cur][i] = now - ans[cur][i] + add(queries[cur][i].first, queries[cur][i].second, lvl[cur]); //printf("found on exit %d with added %d\n", now, add(queries[cur][i].first, queries[cur][i].second, lvl[cur])); } } int sol[MAXN]; inline void solve() { int root = -1, cnt = 0; for (int i=0; i < n; ++i) if (par[i] == -1) { root = i; cnt ++; } assert(cnt == 1); dfs(root); for (int i=0; i < n; ++i) for (int j=0; j < (int) queries[i].size(); ++j) sol[ queries[i][j].idx ] = ans[i][j]; } inline void read() { scanf("%d", &n); assert(n > 0); assert(n <= MAXN); for (int i=0; i < n; ++i) { scanf("%d", &par[i]); assert(par[i] > -2); assert(par[i] <= n); if (par[i] != -1) vec[--par[i]].push_back(i); } scanf("%d", &q); for (int i=0; i < q; ++i) { int id, from, to; scanf("%d%d%d", &id, &from, &to); assert( (id >= 1) && (id <= n) ); assert( abs(from) <= MAXN ); assert( abs(to) <= MAXN ); assert( from <= to ); id --; queries[id].push_back( node(from, to, i) ); } } inline void print() { for (int i=0; i < q; ++i) printf("%d\n", sol[i]); } int main() { freopen("tree.in", "r", stdin); freopen("tree.out", "w", stdout); read(); solve(); print(); return 0; }