#include <bits/stdc++.h>
using namespace std;
inline long long read() {
  long long f = 1, x = 0;
  char ch = getchar();
  while (!isdigit(ch)) {
    if (ch == '-') f = -1;
    ch = getchar();
  }
  while (isdigit(ch)) {
    x = x * 10 + ch - '0';
    ch = getchar();
  }
  return x * f;
}
const int MAXN = 5e4 + 5;
struct SegmentTree {
  int cnt, rt[MAXN], ls[MAXN * 200], rs[MAXN * 200];
  long long sum[MAXN * 200], tag[MAXN * 200];
  void pushDown(int p, int l, int r) {
    if (!tag[p]) return;
    if (!ls[p]) ls[p] = ++cnt;
    if (!rs[p]) rs[p] = ++cnt;
    int mid = (l + r) >> 1;
    int szl = (mid - l + 1), szr = (r - mid);
    sum[ls[p]] += tag[p] * szl;
    sum[rs[p]] += tag[p] * szr;
    tag[ls[p]] += tag[p];
    tag[rs[p]] += tag[p];
    tag[p] = 0;
  }
  void pushUp(int p) { sum[p] = sum[ls[p]] + sum[rs[p]]; }
  void modify(int &p, int tl, int tr, int ql, int qr, int x) {
    if (!p) p = ++cnt;
    if (ql <= tl && qr >= tr) {
      sum[p] += (long long)x * (tr - tl + 1);
      tag[p] += x;
      return;
    }
    pushDown(p, tl, tr);
    int mid = (tl + tr) >> 1;
    if (ql <= mid) modify(ls[p], tl, mid, ql, qr, x);
    if (qr > mid) modify(rs[p], mid + 1, tr, ql, qr, x);
    pushUp(p);
  }
  long long query(int p, int tl, int tr, int ql, int qr) {
    if (!p) return 0;
    if (ql <= tl && qr >= tr) return sum[p];
    pushDown(p, tl, tr);
    int mid = (tl + tr) >> 1;
    long long res = 0;
    if (ql <= mid) res += query(ls[p], tl, mid, ql, qr);
    if (qr > mid) res += query(rs[p], mid + 1, tr, ql, qr);
    pushUp(p);
    return res;
  }
  SegmentTree() {}
} T;
int n, m, Q, C, a[MAXN], b[MAXN];
struct EDGE {
  int next, to;
} edge[MAXN];
int head[MAXN], tot;
inline void addedge(int u, int v) {
  edge[++tot].next = head[u];
  edge[tot].to = v;
  head[u] = tot;
}
int sz[MAXN], dep[MAXN], fa[MAXN], son[MAXN];
void dfs1(int u) {
  sz[u] = 1;
  dep[u] = dep[fa[u]] + 1;
  for (int i = head[u]; i; i = edge[i].next) {
    int v = edge[i].to;
    fa[v] = u;
    dfs1(v);
    sz[u] += sz[v];
    if (sz[v] > sz[son[u]]) son[u] = v;
  }
}
int top[MAXN], dfn[MAXN], cnt;
void dfs2(int u, int tp) {
  dfn[u] = ++cnt;
  top[u] = tp;
  if (son[u]) dfs2(son[u], tp);
  for (int i = head[u]; i; i = edge[i].next) {
    int v = edge[i].to;
    if (v != son[u]) dfs2(v, v);
  }
}
inline long long ask(int col, int u) {
  long long res = 0;
  while (u) {
    res += T.query(T.rt[col], 1, n, dfn[top[u]], dfn[u]);
    u = fa[top[u]];
  }
  return res;
}
inline void add(int col, int u, int x) {
  while (u) {
    T.modify(T.rt[col], 1, n, dfn[top[u]], dfn[u], x);
    u = fa[top[u]];
  }
}
long long s[MAXN], sd[MAXN];
inline void ins(int col, int u) {
  sd[col] += dep[u];
  s[col] += 2LL * ask(col, u);
  s[col] += dep[u];
  add(col, u, 1);
}
inline void del(int col, int u) {
  sd[col] -= dep[u];
  add(col, u, -1);
  s[col] -= 2LL * ask(col, u);
  s[col] -= dep[u];
}
int main() {
  ios::sync_with_stdio(0);
  cin.tie(0);
  n = read();
  m = read();
  Q = read();
  C = read();
  for (int i = 1; i <= n; ++i) a[i] = read();
  for (int i = 2; i <= n; ++i) addedge(read(), i);
  for (int i = 1; i <= m; ++i) b[i] = read();
  dfs1(1);
  dfs2(1, 1);
  for (int i = 1; i <= n; ++i) ins(a[i], i);
  while (Q--) {
    int t = read();
    if (t == 1) {
      int x = read(), y = read();
      del(a[x], x);
      a[x] = y;
      ins(a[x], x);
    } else {
      int x = read();
      long double ans =
          ((long double)s[x] * b[x] * b[x] -
           2.0 * (long double)b[x] * C * sd[x] + (long double)C * C * n) /
          ((long double)n);
      cout << setiosflags(ios::fixed) << setprecision(10) << ans << endl;
    }
  }
  return 0;
}
