#include <bits/stdc++.h>
using namespace std;
typedef int ll;
const ll blk = 316;
const int 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];
// Instead of an unordered_set for deplist (indexed by color), we use a vector
vector<ll> deplist[MAXN];
// We change the dp arrays from fixed global arrays of unordered_map to vectors of unordered_map.
// (This way, if n < MAXN, we are not “wasting” space.)
vector<unordered_map<ll,ll>> dp(MAXN), dp2(MAXN), dp3(MAXN), dp4(MAXN), dp5(MAXN), colVec(MAXN);
// The answer is stored as a pair; note that we update the second element as negative so that
// using max() gives the lexicographically maximum pair.
pair<ll,ll> ans = make_pair(-1000000000, -1000000000);
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 an unordered_set, just push_back the depth.
deplist[color[x]].push_back(dep[x]);
}
void precomp2(ll x = 0) {
// For every node x, record (in a map per color) the frequency of each depth.
colVec[color[x]][dep[x]]++;
for (ll u : adj[x]) {
precomp2(u);
// Merge dp[u] into dp[x] using the “small-to–large” trick.
if (dp[x].size() < dp[u].size()) swap(dp[x], dp[u]);
for (auto &p : dp[u])
dp[x][p.first] += p.second;
dp[u].clear(); // free memory from child's dp after merging
}
dp[x][dep[x]]++;
// Build dp2 for node x – only for depths that appear for the color of x.
for (ll d : deplist[color[x]])
dp2[x][d] += dp[x][d];
}
void dfs(ll x, ll c, ll yes = 1) {
for (ll u : adj[x]) {
dfs(u, c, yes & (color[x] != c));
// Merge dp4[u] into dp4[x]
if (dp4[x].size() < dp4[u].size()) swap(dp4[x], dp4[u]);
for (auto &p : dp4[u])
dp4[x][p.first] += p.second;
dp4[u].clear();
// Merge dp5[u] into dp5[x]
if (dp5[x].size() < dp5[u].size()) swap(dp5[x], dp5[u]);
for (auto &p : dp5[u])
dp5[x][p.first] += p.second;
dp5[u].clear();
}
if (yes && color[x] == c) {
ll res = 0, res2 = 0;
// Iterate only over the unique depths for color c.
for (ll d : deplist[c]) {
if (d <= dep[x]) continue;
ll take = min(dp4[x][d], colVec[c][d]);
res += take;
res2 += max(0, take - dp5[x][d]);
}
ans = max(ans, make_pair(res, -res2));
}
dp4[x][dep[x]]++;
if (c == color[x])
dp5[x][dep[x]]++;
}
void solve(ll c) {
int sz = nodelist[c].size();
// Precompute dp3 for nodes of color c.
for (int i = 0; i < sz; i++) {
ll x = nodelist[c][i];
for (int j = i + 1; j < sz; j++) {
ll 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 (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 take = min(dp2[x][d], colVec[c][d]);
res += take;
res2 += max(0, take - dp3[x][d]);
}
ans = max(ans, make_pair(res, -res2));
}
// Clear dp3 for nodes of color c to free memory.
for (int i = 0; i < sz; i++) {
ll x = nodelist[c][i];
dp3[x].clear();
}
}
int main(){
ios_base::sync_with_stdio(false);
cin.tie(NULL);
cin >> n >> k;
for (ll i = 0; i < n; i++){
cin >> color[i];
cnt[color[i]]++;
nodelist[color[i]].push_back(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]].push_back(i);
}
precomp1();
// For each color, sort and unique–ify the deplist vector so that we don’t iterate duplicate 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]) {
// For every DFS run we clear the dp4/dp5 arrays for all nodes
for (ll j = 0; j < n; j++){
dp4[j].clear();
dp5[j].clear();
}
dfs(0, i, 1);
} else {
solve(i);
}
// Free memory no longer needed for this color.
colVec[i].clear();
deplist[i].clear();
}
cout << ans.first + 1 << " " << -ans.second << "\n";
return 0;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |