Submission #408829

#TimeUsernameProblemLanguageResultExecution timeMemory
408829vuhoanggiapRegions (IOI09_regions)C++17
100 / 100
4230 ms29820 KiB
#include <bits/stdc++.h> #define pb push_back #define all(x) (x).begin(), (x).end() using namespace std; const int maxN = 2e5 + 5, maxR = 25005; const int blocksize = 500; int n, regions, q; vector<int> adj[maxN], R[maxR]; int id[maxN]; int euler; int s[maxN], e[maxN]; void dfs(int u) { s[u] = ++euler; for(auto v : adj[u]) dfs(v); e[u] = euler; } int idxLarge[maxN]; vector<int> large; vector<vector<int> > subLarge, ancLarge; int dfsSubtree(int u, int reg) { int subtree = (id[u] == reg); for(auto v : adj[u]) subtree += dfsSubtree(v, reg); subLarge[idxLarge[reg]][id[u]] += subtree; return subtree; } void dfsAncestor(int u, int reg, int cnt = 0) { cnt += (id[u] == reg); ancLarge[idxLarge[reg]][id[u]] += cnt; for(auto v : adj[u]) dfsAncestor(v, reg, cnt); } void solvelarge() { subLarge.resize((int)large.size() + 1, vector<int>(regions, 0)); ancLarge.resize((int)large.size() + 1, vector<int>(regions, 0)); for(int i = 1; i <= (int)large.size(); i++) { int reg = large[i - 1]; idxLarge[reg] = i; dfsSubtree(1, reg); dfsAncestor(1, reg); } } inline bool cmp(const int &u, const int &v) { return s[u] < s[v]; } inline bool isanc(const int &u, const int &v) { return s[u] <= s[v] && e[v] <= e[u]; } int solve(int r1, int r2) { int ret = 0; int p1 = 0, p2 = 0; vector<int> vert, anc; while(p1 < (int)R[r1].size() && p2 < (int)R[r2].size()) { if(cmp(R[r1][p1], R[r2][p2])) vert.pb(R[r1][p1++]); else vert.pb(R[r2][p2++]); } while(p1 < (int)R[r1].size()) vert.pb(R[r1][p1++]); while(p2 < (int)R[r2].size()) vert.pb(R[r2][p2++]); assert(is_sorted(all(vert), cmp)); for(auto u : vert) { while(!anc.empty() && !isanc(anc.back(), u)) anc.pop_back(); if(id[u] == r1) anc.pb(u); else ret += (int)anc.size(); } return ret; } signed main() { cin >> n >> regions >> q; for(int i = 1; i <= n; i++) { if(i == 1) cin >> id[i], R[id[i]].pb(i); else { int par; cin >> par >> id[i]; adj[par].pb(i); R[id[i]].pb(i); } } dfs(1); for(int reg = 1; reg <= regions; reg++) sort(all(R[reg]), cmp); for(int reg = 1; reg <= regions; reg++) { if((int)R[reg].size() > blocksize) { large.pb(reg); } } solvelarge(); for(int i = 1; i <= q; i++) { int reg1, reg2; cin >> reg1 >> reg2; if(R[reg1].size() > blocksize) { cout << ancLarge[idxLarge[reg1]][reg2] << endl; } else if(R[reg2].size() > blocksize) { cout << subLarge[idxLarge[reg2]][reg1] << endl; } else { cout << solve(reg1, reg2) << endl; } } }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...