제출 #895441

#제출 시각아이디문제언어결과실행 시간메모리
895441MinaRagy06Regions (IOI09_regions)C++17
100 / 100
3688 ms46600 KiB
#include <bits/stdc++.h> using namespace std; #define ll long long const int N = 200'005, inf = 1e9 + 5; vector<int> adj[N]; int a[N], p[N], sz[N], order[N], idx[N]; vector<int> above[N], below[N], gud[N]; void calc1(int i, int c, int r) { above[r][a[i]] += c; above[r][a[i]] = min(above[r][a[i]], inf); c += a[i] == order[r]; for (auto nxt : adj[i]) { calc1(nxt, c, r); } } int calc2(int i, int r) { int c = 0; for (auto nxt : adj[i]) { c += calc2(nxt, r); } below[r][a[i]] += c; below[r][a[i]] = min(below[r][a[i]], inf); return c + (a[i] == order[r]); } int st[N], en[N], t; void dfs(int i) { st[i] = t++; for (auto nxt : adj[i]) { dfs(nxt); } en[i] = t - 1; } int main() { ios_base::sync_with_stdio(0), cin.tie(0); memset(idx, -1, sizeof idx); int n, r, q; cin >> n >> r >> q; cin >> a[0]; a[0]--; for (int i = 1; i < n; i++) { cin >> p[i] >> a[i]; p[i]--; a[i]--; adj[p[i]].push_back(i); } for (int i = 0; i < n; i++) { sz[a[i]]++; gud[a[i]].push_back(i); } for (int i = 0; i < r; i++) { order[i] = i; } sort(order, order + r, [&](int x, int y) { return sz[x] > sz[y]; }); int ttl = 0, ttl2 = 0; for (int i = 0; i < r; i++) { if (!(ttl + r < int(7e5) && ttl2 + n + r < int(1e8))) { break; } idx[order[i]] = i; above[i].resize(r); below[i].resize(r); ttl += r; ttl2 += n + r; calc1(0, 0, i); calc2(0, i); } dfs(0); for (int i = 0; i < r; i++) { sort(gud[i].begin(), gud[i].end(), [&] (int x, int y) { return st[x] < st[y]; }); } while (q--) { int r1, r2; cin >> r1 >> r2; r1--, r2--; if (~idx[r1]) { cout << above[idx[r1]][r2] << endl; } else if (~idx[r2]) { cout << below[idx[r2]][r1] << endl; } else { int m = gud[r2].size(); int bit[m]{}; auto upd = [&] (int x, int v) { for (int i = x; i < m; i = (i | (i + 1))) { bit[i] += v; } }; auto get = [&] (int x) { int ret = 0; for (int i = x; i >= 0; i = (i & (i + 1)) - 1) { ret += bit[i]; } return ret; }; vector<int> cur = gud[r2]; for (auto &x : cur) { x = st[x]; } for (auto x : gud[r1]) { int s = lower_bound(cur.begin(), cur.end(), st[x]) - cur.begin(); int e = upper_bound(cur.begin(), cur.end(), en[x]) - cur.begin() - 1; if (s <= e) { upd(s, 1); if (e + 1 < m) { upd(e + 1, -1); } } } int ans = 0; for (int i = 0; i < m; i++) { ans += get(i); } cout << ans << endl; } } return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...