제출 #1145613

#제출 시각아이디문제언어결과실행 시간메모리
1145613monkey133Team Coding (EGOI24_teamcoding)C++20
62 / 100
4011 ms1114112 KiB
#include <bits/stdc++.h> using namespace std; //–––– Custom hash (unchanged) –––– struct custom_hash { static uint64_t splitmix64(uint64_t x) { x += 0x9e3779b97f4a7c15ULL; x = (x ^ (x >> 30)) * 0xbf58476d1ce4e5b9ULL; x = (x ^ (x >> 27)) * 0x94d049bb133111ebULL; return x ^ (x >> 31); } size_t operator()(uint64_t x) const { static const uint64_t random_constant = chrono::steady_clock::now().time_since_epoch().count(); return splitmix64(x + random_constant); } }; //–––– Typedefs and macros –––– typedef int ll; typedef pair<ll,ll> pi; #define pb push_back #define mp make_pair ll const blk = 316; //–––– Global variables –––– const ll MAXN = 100005; ll n, k, label = 0; ll color[MAXN], par[MAXN], in[MAXN], out[MAXN], cnt[MAXN], dep[MAXN], big[MAXN]; vector<ll> adj[MAXN], nodelist[MAXN]; vector<ll> deplist[MAXN]; // for each color, record all depths // We use vectors of unordered_maps (with custom_hash) for our DP arrays. vector<unordered_map<ll,ll, custom_hash>> dp(MAXN), dp2(MAXN), dp3(MAXN), dp4(MAXN), dp5(MAXN), colMap(MAXN); // Answer stored as (res, -swaps) so that max() works lexicographically. pi ans = mp(-1000000000, -1000000000); //–––– precomp1: 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; // Instead of inserting into a set, just push_back. deplist[color[x]].pb(dep[x]); } //–––– precomp2: DSU–on–Tree merging using unordered_map –––– void precomp2(ll x = 0) { colMap[color[x]][dep[x]]++; // update global frequency for this color for (ll u : adj[x]) { precomp2(u); // Merge dp[u] into dp[x]: swap if dp[x] is smaller if(dp[x].size() < dp[u].size()) swap(dp[x], dp[u]); // Pre–reserve: add size of dp[u] to dp[x] to avoid rehashing overhead. dp[x].reserve(dp[x].size() + dp[u].size()); for(auto it = dp[u].begin(); it != dp[u].end(); ++it) dp[x][it->first] += it->second; dp[u].clear(); } dp[x][dep[x]]++; // For “small” colors, also build dp2[x]. if (!big[color[x]]) { for (ll d : deplist[color[x]]) dp2[x][d] += dp[x][d]; } } //–––– dfs: process “big” colors using DSU–merging on dp4 and dp5 –––– 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]); dp4[x].reserve(dp4[x].size() + dp4[u].size()); for(auto it = dp4[u].begin(); it != dp4[u].end(); ++it) dp4[x][it->first] += it->second; if(dp5[x].size() < dp5[u].size()) swap(dp5[x], dp5[u]); dp5[x].reserve(dp5[x].size() + dp5[u].size()); for(auto it = dp5[u].begin(); it != dp5[u].end(); ++it) dp5[x][it->first] += it->second; dp4[u].clear(); dp5[u].clear(); } if(yes && color[x] == c) { ll res = 0, res2 = 0; // Loop only over unique depths for color c. for (ll d : deplist[c]) { if(d <= dep[x]) continue; ll a = dp4[x][d]; ll b = colMap[c][d]; ll take = a < b ? a : b; res += take; ll cval = dp5[x][d]; res2 += take > cval ? take - cval : 0; } ans = max(ans, mp(res, -res2)); } dp4[x][dep[x]]++; if(c == color[x]) dp5[x][dep[x]]++; } //–––– solve: process “small” colors –––– void solve(ll c) { int sz = nodelist[c].size(); // For every pair (x,y) with x an ancestor of y among nodes of color c. 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]) dp3[x][dep[y]]++; } } // For each node x of color c, combine dp2[x] and dp3[x] to update answer. for (int i = 0; i < sz; i++) { ll x = nodelist[c][i]; ll res = 0, res2 = 0; for (ll d : deplist[c]) { if(d <= dep[x]) continue; ll a = dp2[x][d]; ll b = colMap[c][d]; ll take = a < b ? a : b; res += take; ll cval = dp3[x][d]; res2 += take > cval ? take - cval : 0; } dp2[x].clear(); dp3[x].clear(); ans = max(ans, mp(res, -res2)); } } //–––– Main –––– int main(){ ios::sync_with_stdio(false); cin.tie(nullptr); cout.tie(nullptr); cin >> n >> 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(); // Process each color: use DFS for “big” colors; use solve() for “small” colors. for (ll i = 0; i < k; i++){ if (big[i]) { 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...