Submission #1145598

#TimeUsernameProblemLanguageResultExecution timeMemory
1145598monkey133Team Coding (EGOI24_teamcoding)C++20
0 / 100
4094 ms45840 KiB
#include <bits/stdc++.h> using namespace std; typedef int ll; typedef pair<int,int> pi; const int MAXN = 100005; int n, k, label = 0; int blk = 316; int color[MAXN], par[MAXN], in[MAXN], out[MAXN], cnt[MAXN], dep[MAXN]; int big[MAXN]; vector<int> adj[MAXN], nodelist[MAXN]; vector<int> deplist[MAXN]; // for each color, record all depths (later sorted & uniqued) // We'll store frequency maps as sorted vectors of (key, count) pairs. vector<pi> dp[MAXN], dp2[MAXN], dp3[MAXN], dp4[MAXN], dp5[MAXN]; // For each color (0<=c<k) store the global frequency of nodes of that color by depth. vector<vector<pi>> colMapVec; // size = k, indexed by color // The final answer is stored as (res, -swaps) so that max() gives lex–order. pi ans = { -1000000000, -1000000000 }; // ----- Helper routines for “dp” vectors (sorted by key) ----- // Binary search for key in sorted vector "vec"; returns count if found, else 0. inline int getValue(const vector<pi>& vec, int key) { int lo = 0, hi = (int)vec.size()-1; while(lo <= hi) { int mid = (lo+hi)/2; if(vec[mid].first == key) return vec[mid].second; else if(vec[mid].first < key) lo = mid+1; else hi = mid-1; } return 0; } // Insert or update key in sorted vector "vec" by adding "val". inline void addValue(vector<pi>& vec, int key, int val) { auto it = std::lower_bound(vec.begin(), vec.end(), make_pair(key,0)); if(it != vec.end() && it->first == key) it->second += val; else vec.insert(it, {key, val}); } // Merge two sorted vectors (dest and src) summing counts for equal keys. inline void mergeSortedVectors(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.push_back({dest[i].first, dest[i].second + src[j].second}); i++; j++; } else if(dest[i].first < src[j].first){ merged.push_back(dest[i]); i++; } else { merged.push_back(src[j]); j++; } } while(i < dest.size()){ merged.push_back(dest[i]); i++; } while(j < src.size()){ merged.push_back(src[j]); j++; } dest = move(merged); } // ----- DFS 1: Euler Tour + depth computation; record each node’s depth in deplist[color] ----- void precomp1(int x = 0) { in[x] = ++label; for (int u: adj[x]) { dep[u] = dep[x] + 1; precomp1(u); } out[x] = label; deplist[color[x]].push_back(dep[x]); } // ----- DFS 2: DSU on tree for "dp" arrays; also build dp2 for later use for small colors ----- void precomp2(int x = 0) { // Update global frequency for this node’s color. addValue(colMapVec[color[x]], dep[x], 1); for (int 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]); mergeSortedVectors(dp[x], dp[u]); dp[u].clear(); } addValue(dp[x], dep[x], 1); // Build dp2[x] for nodes whose color is “small” if (!big[color[x]]) { for (int d: deplist[color[x]]) { int val = getValue(dp[x], d); if(val) addValue(dp2[x], d, val); } } } // ----- DFS for “big” colors: merge dp4 and dp5 arrays ----- void dfs(int x, int c, int yes = 1) { for (int u: adj[x]) { dfs(u, c, yes & (color[x] != c)); if(dp4[x].size() < dp4[u].size()) swap(dp4[x], dp4[u]); mergeSortedVectors(dp4[x], dp4[u]); if(dp5[x].size() < dp5[u].size()) swap(dp5[x], dp5[u]); mergeSortedVectors(dp5[x], dp5[u]); dp4[u].clear(); dp5[u].clear(); } if(yes && color[x] == c) { int res = 0, res2 = 0; // For every depth (from the unique depths for color c) that is deeper than dep[x] for (int 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, make_pair(res, -res2)); } addValue(dp4[x], dep[x], 1); if(c == color[x]) addValue(dp5[x], dep[x], 1); } // ----- Process “small” colors (those with cnt <= blk) ----- void solve(int c) { int sz = nodelist[c].size(); // For every pair of nodes of color c where one is an ancestor of the other, // update dp3 for the ancestor. for (int i = 0; i < sz; i++){ int x = nodelist[c][i]; for (int j = i+1; j < sz; j++){ int 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); } } // Then for each node of color c, use its dp2 and dp3 to compute candidate answer. for (int i = 0; i < sz; i++){ int x = nodelist[c][i]; int res = 0, res2 = 0; for (int 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, make_pair(res, -res2)); } } // ----- Main ----- int main(){ ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); cin >> n >> k; // Initialize colMapVec so that colMapVec[c] will hold frequency (by depth) for color c. colMapVec.resize(k); for (int i = 0; i < n; i++){ cin >> color[i]; cnt[color[i]]++; nodelist[color[i]].push_back(i); } for (int i = 0; i < k; i++){ if(cnt[i] > blk) big[i] = 1; } for (int i = 1; i < n; i++){ cin >> par[i]; adj[par[i]].push_back(i); } precomp1(); // For each color, sort and unique the list of depths (to drive our loops later) for (int 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(); // Process each color: use DFS for big colors and a different method for small colors. for (int i = 0; i < k; i++){ if(big[i]){ for (int 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...