You are given a rooted tree on n vertices, its root is the vertex number 1. The i-th vertex contains a number w_i. Split it into the minimum possible number of vertical paths in such a way that each path contains no more than L vertices and the sum of integers w_i on each path does not exceed S. Each vertex should belong to exactly one path.

A vertical path is a sequence of vertices v_1, v_2, …, v_k where v_i (i ≥ 2) is the parent of v_{i - 1}.

Input

The first line contains three integers n, L, S (1 ≤ n ≤ 10^5, 1 ≤ L ≤ 10^5, 1 ≤ S ≤ 10^{18}) — the number of vertices, the maximum number of vertices in one path and the maximum sum in one path.

The second line contains n integers w_1, w_2, …, w_n (1 ≤ w_i ≤ 10^9) — the numbers in the vertices of the tree.

The third line contains n - 1 integers p_2, …, p_n (1 ≤ p_i < i), where p_i is the parent of the i-th vertex in the tree.

Output

Output one number — the minimum number of vertical paths. If it is impossible to split the tree, output -1.

Examples

Input

3 1 3
1 2 3
1 1


Output

3

Input

3 3 6
1 2 3
1 1


Output

2

Input

1 1 10000
10001


Output

-1

Note

In the first sample the tree is split into \{1\},\ \{2\},\ \{3\}.

In the second sample the tree is split into \{1,\ 2\},\ \{3\} or \{1,\ 3\},\ \{2\}.

In the third sample it is impossible to split the tree.
#include <bits/stdc++.h>
using namespace std;
const int MAXN = 111111;
const long long INF = 1000000;
struct IntervalTree {
  long long valmax[MAXN * 4];
  long long valmin[MAXN * 4];
  long long add[MAXN * 4];
  int low[MAXN * 4], high[MAXN * 4];
  int maxpos[MAXN * 4];
  int minpos[MAXN * 4];
  IntervalTree() {}
  IntervalTree(int n) { Init(n, 0); }
  IntervalTree(int n, long long base) { Init(n, base); }
  void BuildNode(int s, int l, int h, long long base) {
    low[s] = l;
    high[s] = h;
    valmax[s] = base;
    valmin[s] = base;
    minpos[s] = base;
    maxpos[s] = base;
    add[s] = 0;
    if (l < h) {
      int m = (l + h) / 2;
      BuildNode(s * 2, l, m, base);
      BuildNode(s * 2 + 1, m + 1, h, base);
    }
  }
  void LazyUpdateNode(int s) {
    add[s * 2] += add[s];
    add[s * 2 + 1] += add[s];
    valmax[s * 2] += add[s];
    valmax[s * 2 + 1] += add[s];
    valmin[s * 2] += add[s];
    valmin[s * 2 + 1] += add[s];
    add[s] = 0;
  }
  void AfterUpdate(int s) {
    valmax[s] = max(valmax[s * 2], valmax[s * 2 + 1]);
    valmin[s] = min(valmin[s * 2], valmin[s * 2 + 1]);
  }
  long long GetMaxNode(int s, int l, int h) {
    if (l <= low[s] && high[s] <= h) {
      return valmax[s];
    }
    LazyUpdateNode(s);
    long long ans = 0;
    if (l <= high[s * 2]) ans = max(ans, GetMaxNode(s * 2, l, h));
    if (h > high[s * 2]) ans = max(ans, GetMaxNode(s * 2 + 1, l, h));
    return ans;
  }
  long long GetMinNode(int s, int l, int h) {
    if (l <= low[s] && high[s] <= h) {
      return valmin[s];
    }
    LazyUpdateNode(s);
    long long ans = INF;
    if (l <= high[s * 2]) ans = min(ans, GetMinNode(s * 2, l, h));
    if (h > high[s * 2]) ans = min(ans, GetMinNode(s * 2 + 1, l, h));
    return ans;
  }
  void AddRangeNode(int s, int l, int h, long long v) {
    if (l <= low[s] && high[s] <= h) {
      add[s] += v;
      valmax[s] += v;
      valmin[s] += v;
      return;
    }
    LazyUpdateNode(s);
    if (l <= high[s * 2]) AddRangeNode(s * 2, l, h, v);
    if (h > high[s * 2]) AddRangeNode(s * 2 + 1, l, h, v);
    AfterUpdate(s);
  }
  void UpdateNode(int s, int p, long long v) {
    if (low[s] == high[s]) {
      valmax[s] = v;
      valmin[s] = v;
      return;
    }
    LazyUpdateNode(s);
    if (p <= high[s * 2])
      UpdateNode(s * 2, p, v);
    else
      UpdateNode(s * 2 + 1, p, v);
    AfterUpdate(s);
  }
  int GetPosMaxNode(int s, int l, int h) {
    if (low[s] == high[s]) {
      return low[s];
    } else {
      if (l <= high[s * 2]) {
        if (h > high[s * 2]) {
          return (GetMaxNode(s * 2, l, h) >= GetMaxNode(s * 2 + 1, l, h)
                      ? GetPosMaxNode(s * 2, l, h)
                      : GetPosMaxNode(s * 2 + 1, l, h));
        }
        return GetPosMaxNode(s * 2, l, h);
      }
      return GetPosMaxNode(s * 2 + 1, l, h);
    }
  }
  int GetPosMinNode(int s, int l, int h) {
    if (low[s] == high[s]) {
      return low[s];
    } else {
      if (l <= high[s * 2]) {
        if (h > high[s * 2]) {
          return (GetMinNode(s * 2, l, h) <= GetMinNode(s * 2 + 1, l, h)
                      ? GetPosMinNode(s * 2, l, h)
                      : GetPosMinNode(s * 2 + 1, l, h));
        }
        return GetPosMinNode(s * 2, l, h);
      }
      return GetPosMinNode(s * 2 + 1, l, h);
    }
  }
  void AddRange(int l, int h, long long v) { AddRangeNode(1, l, h, v); }
  long long GetMin(int l, int h) { return GetMinNode(1, l, h); }
  long long GetMax(int l, int h) { return GetMaxNode(1, l, h); }
  int GetPosMin(int l, int h) { return GetPosMinNode(1, l, h); }
  int GetPosMax(int l, int h) { return GetPosMaxNode(1, l, h); }
  void Update(int p, long long v) { UpdateNode(1, p, v); }
  void Init(int n, long long base) {
    memset(add, 0, sizeof(add));
    BuildNode(1, 1, n, base);
  }
};
long long w[MAXN];
vector<int> edges[MAXN];
int n, MaxLength;
long long MaxWeight;
int cnt = 0;
int h[MAXN], lft[MAXN], rgt[MAXN], dp[MAXN], s[MAXN];
vector<pair<int, int> > st;
IntervalTree IT, WIT;
void NumberTree(int u, int h) {
  lft[u] = ++cnt;
  st.push_back(make_pair(h, u));
  for (int i = 0; i < edges[u].size(); ++i) {
    NumberTree(edges[u][i], h + 1);
  }
  rgt[u] = cnt;
}
int main() {
  cin >> n >> MaxLength >> MaxWeight;
  for (int i = 1; i <= n; ++i) {
    cin >> w[i];
  }
  for (int i = 2; i <= n; ++i) {
    int p;
    cin >> p;
    edges[p].push_back(i);
  }
  int root = 1, height = 0;
  NumberTree(root, height);
  sort(st.begin(), st.end());
  IT.Init(n, INF);
  WIT.Init(n, 0);
  for (int i = int(st.size()) - 1; i >= 0; --i) {
    int u = st[i].second, h = st[i].first;
    s[u] = 0;
    for (int j = 0; j < edges[u].size(); ++j) {
      int v = edges[u][j];
      s[u] += dp[v];
    }
    WIT.AddRange(lft[u], rgt[u], w[u]);
    while (WIT.GetMax(lft[u], rgt[u]) > MaxWeight) {
      int p = WIT.GetPosMax(lft[u], rgt[u]);
      IT.Update(p, INF);
      WIT.Update(p, 0);
    }
    while (st.back().first - h >= MaxLength) {
      int v = st.back().second;
      IT.Update(lft[v], INF);
      st.pop_back();
    }
    dp[u] = (w[u] <= MaxWeight ? 1 : INF) + s[u];
    if (lft[u] < rgt[u]) {
      dp[u] = min((long long)dp[u], IT.GetMin(lft[u] + 1, rgt[u]) + 1 + s[u]);
    }
    if (dp[u] >= INF) {
      cout << -1;
      return 0;
    }
    WIT.Update(lft[u], w[u]);
    IT.Update(lft[u], 0);
    IT.AddRange(lft[u], rgt[u], s[u] - dp[u]);
  }
  cout << dp[1] << endl;
  return 0;
}
