#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define pf push_front
#define mp make_pair
#define fi first
#define se second
#define int long long
#define all(x) (x).begin(), (x).end()
typedef long double ld;
typedef long long ll;
typedef pair<ll,ll> pll;
typedef pair<int,int> pii;
typedef vector<int> vi;
typedef vector<ll> vll;
typedef vector<bool> vb;
typedef vector<vector<int>> vvi;
typedef vector<vector<bool>> vvb;
typedef vector<vector<ll>> vvll;
typedef vector<string> vs;
typedef vector<vector<string>> vvs;
typedef vector<char> vc;
typedef vector<vector<char>> vvc;
typedef map<int, int> mii;
typedef unordered_map<int, int> umii;
const int mod = 1e9 + 7;
const int inf = INTMAX_MAX;
const bool tc = false;
int n, k;
const int mxn = 1e5 + 5;
int p[mxn], a[mxn], c[mxn]; vi adj[mxn], anti[mxn], depths[mxn], nodes[mxn];
int d[mxn], tin[mxn], tout[mxn];
vi tinfordp[mxn];
int timer = -1;
void pre(int node, int prev, int dp) {
tin[node] = ++timer;
d[node] = dp;
tinfordp[d[node]].pb(tin[node]);
depths[a[node]].pb(dp);
nodes[a[node]].pb(node);
for (auto &neigh : adj[node]) {
if (neigh == prev) continue;
pre(neigh, node, dp + 1);
}
tout[node] = timer;
}
int seen[mxn];
void antidfs(int node, int prev) {
bool rs = false;
if (!seen[a[node]]) {
anti[a[node]].pb(node);
seen[a[node]] = 1;
rs = true;
}
for (auto &neighbour : adj[node]) {
if (neighbour == prev) continue;
antidfs(neighbour, node);
}
if (rs) seen[a[node]] = 0;
}
pii solvea(int x) {
// c[x]^2 shenanigans
// iterate over guy and see if work
pii ans = {0, 0};
for (int _1 = 0; _1 < nodes[x].size(); _1++) {
int i = nodes[x][_1];
pii cur = {0, 0};
mii budget;
for (auto &y : nodes[x]) {
// figure out budget for this
int dep = d[y];
if (dep < d[i]) continue;
budget[dep] = (upper_bound(all(tinfordp[dep]), tout[i]) - lower_bound(all(tinfordp[dep]), tin[i]));
}
int alr = 0;
for (auto &y : nodes[x]) {
if (tin[i] <= tin[y] && tin[y] <= tout[i]) {
alr++;
budget[d[y]]--;
}
}
for (int _2 = 0; _2 < nodes[x].size(); _2++) {
if (_1 == _2) continue;
int j = nodes[x][_2];
if (tin[i] <= tin[j] && tin[j] <= tout[i]) {
// already in
cur.fi++;
continue;
}
if (d[j] == d[i]) continue;
if (!budget[d[j]]) continue;
cur.fi++; cur.se++;
budget[d[j]]--;
}
ans = max(ans, cur);
}
ans.fi++;
return ans;
}
int cd[mxn]; // count at depths in this guy subtree
void bdfsdo(int node, int prev) {
cd[d[node]]++;
for (auto &v : adj[node]) {
if (v == prev) continue;
bdfsdo(v, node);
}
}
void bdfsundo(int node, int prev) {
cd[d[node]]--;
for (auto &v : adj[node]) {
if (v == prev) continue;
bdfsundo(v, node);
}
}
int alrdfs(int node, int prev, int col) {
int ans = 0;
ans += (a[node]==col);
for (auto &v : adj[node]) {
if (v == prev) continue;
ans += alrdfs(v, node, col);
}
return ans;
}
int bruh[mxn]; // how many of current color im seeing actually at this depth
pii solveb(int x) {
// simple o(n) anticahin
for (auto &y : depths[x]) bruh[y]++;
pii ans = {0, 0};
for (auto &node : anti[x]) {
// go through subtree and keep count for depths
// how many already in this boys subtree
int alr = alrdfs(node, p[node], a[node])-1;
bdfsdo(node, p[node]);
// ans is min of this and actual cnt
int cur = 0;
for (int i = d[node]+1; i < n; i++) {
if (!cd[i]) break;
cur += min(cd[i], bruh[i]);
}
ans = max(ans, {cur, -(cur-alr)});
bdfsundo(node, p[node]);
}
for (auto &y : depths[x]) bruh[y]--;
ans.fi++;
return ans;
}
const int B = 1e5;
inline void solve() {
cin >> n >> k;
for (int i = 0; i < n; i++) {cin >> a[i]; c[a[i]]++;}
for (int i = 1; i < n; i++) {
cin >> p[i];
adj[i].pb(p[i]);
adj[p[i]].pb(i);
}
pre(0, -1, 0); antidfs(0, -1);
for (int i = 0; i < n; i++) sort(all(tinfordp[i]));
pii ans = {-1, 1e18};
for (int i = 0; i < k; i++) {
if (c[i] <= B) ans = max(ans, solvea(i));
else ans = max(ans, solveb(i));
}
cout << ans.fi << " " << abs(-ans.se) << '\n';
}
void setIO(string s) {
freopen((s + ".in").c_str(), "r", stdin);
freopen((s + ".out").c_str(), "w", stdout);
}
signed main() {
ios::sync_with_stdio(false);
cout.tie(0);
cin.tie(0);
//setIO();
int t = 1;
if (tc) {
cin >> t;
}
while (t--) {
solve();
}
}