Submission #1145603

#TimeUsernameProblemLanguageResultExecution timeMemory
1145603monkey133Team Coding (EGOI24_teamcoding)C++20
23 / 100
4091 ms44228 KiB
#include <bits/stdc++.h> using namespace std; //––– Typedefs and macros ––– typedef int ll; typedef pair<ll,ll> pi; #define pb push_back #define mp make_pair const ll MAXN = 100005; ll n, k, label = 0; ll const blk = 316; ll color[MAXN], par[MAXN], in[MAXN], out[MAXN], cnt[MAXN], dep[MAXN], big[MAXN]; vector<ll> adj[MAXN], nodelist[MAXN]; // For each color, we record all depths encountered (then sorted & uniqued) vector<ll> deplist[MAXN]; // Instead of unordered_map, we use sorted vectors of (depth, frequency). vector<pi> dp[MAXN], dp2[MAXN], dp3[MAXN], dp4[MAXN], dp5[MAXN]; // For each color, a global frequency table (by depth) for that color. vector< vector<pi> > colMapVec; // Our final answer is stored as (res, -swaps) so that max() works lexicographically. pi ans = mp(-1000000000, -1000000000); //–––– Helper routines for sorted frequency arrays ––––– // Binary search for key in sorted vector v; returns frequency if found, else 0. int getValue(const vector<pi>& v, int key) { int lo = 0, hi = (int)v.size()-1; while (lo <= hi) { int mid = (lo+hi)/2; if(v[mid].first == key) return v[mid].second; else if(v[mid].first < key) lo = mid+1; else hi = mid-1; } return 0; } // Insert (or update) key in sorted vector v by adding val. void addValue(vector<pi>& v, int key, int val) { auto it = std::lower_bound(v.begin(), v.end(), mp(key, 0)); if(it != v.end() && it->first == key) it->second += val; else v.insert(it, mp(key, val)); } // Merge two sorted vectors (dest and src) and store the merged result in dest. void mergeVectors(vector<pi>& dest, const vector<pi>& src) { vector<pi> merged; merged.reserve(dest.size() + src.size()); int i = 0, j = 0; while(i < dest.size() && j < src.size()){ if(dest[i].first == src[j].first){ merged.pb(mp(dest[i].first, dest[i].second + src[j].second)); i++; j++; } else if(dest[i].first < src[j].first){ merged.pb(dest[i]); i++; } else { merged.pb(src[j]); j++; } } while(i < dest.size()){ merged.pb(dest[i]); i++; } while(j < src.size()){ merged.pb(src[j]); j++; } dest = move(merged); } //–––– DFS 1: Euler Tour and record depths ––––– void precomp1(ll x = 0) { in[x] = ++label; for (ll u : adj[x]) { dep[u] = dep[x] + 1; precomp1(u); } out[x] = label; // Record the depth of this node for its color. deplist[color[x]].pb(dep[x]); } //–––– DFS 2: DSU on Tree ––––– // Build dp[x] (frequency table for subtree x) and update global frequency table colMapVec. void precomp2(ll x = 0) { // Update global frequency for this node’s color. addValue(colMapVec[color[x]], dep[x], 1); for (ll u : adj[x]) { precomp2(u); // Merge dp[u] into dp[x] (small-to–large merging) if (dp[x].size() < dp[u].size()) swap(dp[x], dp[u]); mergeVectors(dp[x], dp[u]); dp[u].clear(); } addValue(dp[x], dep[x], 1); // For “small” colors, build dp2[x] (only for depths that appear for that color). if (!big[color[x]]) { for (ll d : deplist[color[x]]) { int freq = getValue(dp[x], d); if (freq) addValue(dp2[x], d, freq); } } } //–––– DFS for “big” colors: merge dp4 and dp5 arrays ––––– void dfs(ll x, ll c, ll yes = 1) { for (ll u : adj[x]) { dfs(u, c, yes & (color[x] != c)); if (dp4[x].size() < dp4[u].size()) swap(dp4[x], dp4[u]); mergeVectors(dp4[x], dp4[u]); if (dp5[x].size() < dp5[u].size()) swap(dp5[x], dp5[u]); mergeVectors(dp5[x], dp5[u]); dp4[u].clear(); dp5[u].clear(); } if (yes && color[x] == c) { int res = 0, res2 = 0; // Iterate over the unique depths for color c. for (ll d : deplist[c]) { if (d <= dep[x]) continue; int a = getValue(dp4[x], d); int b = getValue(colMapVec[c], d); int take = min(a, b); res += take; int cval = getValue(dp5[x], d); res2 += max(0, take - cval); } ans = max(ans, mp(res, -res2)); } addValue(dp4[x], dep[x], 1); if (c == color[x]) addValue(dp5[x], dep[x], 1); } //–––– Process “small” colors ––––– void solve(ll c) { int sz = nodelist[c].size(); // For every pair (x,y) of nodes of color c with x an ancestor of y, // update dp3 for x. for (int i = 0; i < sz; i++) { for (int j = i + 1; j < sz; j++) { ll x = nodelist[c][i], y = nodelist[c][j]; if (in[x] > in[y]) swap(x, y); if (in[x] <= in[y] && in[y] <= out[x]) addValue(dp3[x], dep[y], 1); } } // For each node of color c, use its dp2 and dp3 to compute a candidate answer. for (int i = 0; i < sz; i++) { ll x = nodelist[c][i]; int res = 0, res2 = 0; for (ll d : deplist[c]) { if (d <= dep[x]) continue; int a = getValue(dp2[x], d); int b = getValue(colMapVec[c], d); int take = min(a, b); res += take; int cval = getValue(dp3[x], d); res2 += max(0, take - cval); } dp2[x].clear(); dp3[x].clear(); ans = max(ans, mp(res, -res2)); } } //–––– Main ––––– int main(){ ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); cin >> n >> k; colMapVec.resize(k); for (ll i = 0; i < n; i++){ cin >> color[i]; cnt[color[i]]++; nodelist[color[i]].pb(i); } for (ll i = 0; i < k; i++){ if (cnt[i] > blk) big[i] = 1; } for (ll i = 1; i < n; i++){ cin >> par[i]; adj[par[i]].pb(i); } precomp1(); // For each color, sort and unique the list of depths. for (ll i = 0; i < k; i++){ sort(deplist[i].begin(), deplist[i].end()); deplist[i].erase(unique(deplist[i].begin(), deplist[i].end()), deplist[i].end()); } precomp2(); for (ll i = 0; i < k; i++){ if (big[i]) { // Clear temporary arrays for the big–color DFS. for (ll j = 0; j < n; j++){ dp5[j].clear(); dp4[j].clear(); } dfs(0, i, 1); } else { solve(i); } } cout << ans.first + 1 << " " << -ans.second << "\n"; return 0; }
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...