#include <bits/stdc++.h>
using namespace std;
const int N = 5e4 + 10;
struct Edge {
  int to, nxt;
} E[N << 2];
int n, m, q, C, cnt, timer, tot;
int a[N], lc[N * 200], rc[N * 200], b[N], head[N], size[N], dep[N], dfn[N],
    fa[N], son[N], top[N], rt[N];
long long res[N * 200], tag[N * 200], sum[N], s[N];
template <typename T>
inline void chkmax(T &x, T y) {
  x = max(x, y);
}
template <typename T>
inline void chkmin(T &x, T y) {
  x = min(x, y);
}
template <typename T>
inline void read(T &x) {
  T f = 1;
  x = 0;
  char c = getchar();
  for (; !isdigit(c); c = getchar())
    if (c == '-') f = -f;
  for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - '0';
  x *= f;
}
inline void pushup(int now) { res[now] = res[lc[now]] + res[rc[now]]; }
inline void pushdown(int now, int l, int r) {
  if (!tag[now]) return;
  if (!lc[now]) lc[now] = ++cnt;
  if (!rc[now]) rc[now] = ++cnt;
  int mid = (l + r) >> 1;
  res[lc[now]] += (long long)(mid - l + 1) * tag[now];
  res[rc[now]] += (long long)(r - mid) * tag[now];
  tag[lc[now]] += (long long)tag[now];
  tag[rc[now]] += (long long)tag[now];
  tag[now] = 0;
  return;
}
inline void modify(int &now, int l, int r, int ql, int qr, int val) {
  if (!now) now = ++cnt;
  if (l == ql && r == qr) {
    res[now] += (long long)(r - l + 1) * val;
    tag[now] += (long long)val;
    return;
  }
  pushdown(now, l, r);
  int mid = (l + r) >> 1;
  if (mid >= qr)
    modify(lc[now], l, mid, ql, qr, val);
  else if (mid + 1 <= ql)
    modify(rc[now], mid + 1, r, ql, qr, val);
  else
    modify(lc[now], l, mid, ql, mid, val),
        modify(rc[now], mid + 1, r, mid + 1, qr, val);
  pushup(now);
}
inline long long query(int now, int l, int r, int ql, int qr) {
  if (!now) return 0;
  if (l == ql && r == qr) return res[now];
  int mid = (l + r) >> 1;
  pushdown(now, l, r);
  if (mid >= qr)
    return query(lc[now], l, mid, ql, qr);
  else if (mid + 1 <= ql)
    return query(rc[now], mid + 1, r, ql, qr);
  else
    return query(lc[now], l, mid, ql, mid) +
           query(rc[now], mid + 1, r, mid + 1, qr);
}
inline void addedge(int u, int v) {
  E[++tot] = (Edge){v, head[u]};
  head[u] = tot;
}
inline void dfs(int u) {
  size[u] = 1;
  dep[u] = dep[fa[u]] + 1;
  for (int i = head[u]; i; i = E[i].nxt) {
    int v = E[i].to;
    if (v == fa[u]) continue;
    fa[v] = u;
    dfs(v);
    size[u] += size[v];
    if (size[v] > size[son[u]]) son[u] = v;
  }
}
inline void efs(int u, int tp) {
  dfn[u] = ++timer;
  top[u] = tp;
  if (son[u]) efs(son[u], tp);
  for (int i = head[u]; i; i = E[i].nxt) {
    int v = E[i].to;
    if (v != fa[u] && v != son[u]) efs(v, v);
  }
}
inline long long ask(int col, int u) {
  long long res = 0;
  while (u) {
    res += query(rt[col], 1, n, dfn[top[u]], dfn[u]);
    u = fa[top[u]];
  }
  return res;
}
inline void add(int col, int u, int val) {
  while (u) {
    modify(rt[col], 1, n, dfn[top[u]], dfn[u], val);
    u = fa[top[u]];
  }
  return;
}
inline void Insert(int col, int u) {
  sum[col] += (long long)dep[u];
  s[col] += (long long)2 * ask(col, u);
  s[col] += (long long)dep[u];
  add(col, u, 1);
}
inline void Delete(int col, int u) {
  sum[col] -= (long long)dep[u];
  add(col, u, -1);
  s[col] -= (long long)2 * ask(col, u);
  s[col] -= (long long)dep[u];
  return;
}
int main() {
  read(n);
  read(m);
  read(q);
  read(C);
  for (int i = 1; i <= n; ++i) read(a[i]);
  for (int i = 2; i <= n; ++i) {
    int x;
    read(x);
    addedge(x, i);
  }
  for (int i = 1; i <= m; ++i) read(b[i]);
  dfs(1);
  efs(1, 1);
  for (int i = 1; i <= n; ++i) Insert(a[i], i);
  while (q--) {
    int opt;
    read(opt);
    if (opt == 1) {
      int x, y;
      read(x), read(y);
      Delete(a[x], x);
      a[x] = y;
      Insert(a[x], x);
    } else {
      int x;
      read(x);
      double ans = ((double)s[x] * b[x] * b[x] -
                    2.0 * (double)b[x] * C * sum[x] + (double)C * C * n) /
                   ((double)n);
      printf("%.10lf\n", ans);
    }
  }
  return 0;
}
