#include <bits/stdc++.h>
using namespace std;
const int maxn = 50005;
int n, m, q, c, k;
vector<int> edge[maxn];
vector<pair<int, int> > eve[maxn];
int a[maxn], b[maxn], dfn[maxn], son[maxn], sz[maxn], top[maxn], par[maxn];
long long ans[maxn];
namespace Segtree {
long long val[maxn * 4][3], tag[maxn * 4];
void apply(int cur, long long v) {
  val[cur][2] += v * v * val[cur][0] + 2 * v * val[cur][1];
  val[cur][1] += v * val[cur][0];
  tag[cur] += v;
}
void pushdown(int cur) {
  if (tag[cur]) {
    apply(cur << 1, tag[cur]);
    apply(cur << 1 | 1, tag[cur]);
    tag[cur] = 0;
  }
}
void pushup(int cur) {
  val[cur][0] = val[cur << 1][0] + val[cur << 1 | 1][0];
  val[cur][1] = val[cur << 1][1] + val[cur << 1 | 1][1];
  val[cur][2] = val[cur << 1][2] + val[cur << 1 | 1][2];
}
void build(int cur, int l, int r) {
  if (l == r) {
    val[cur][0] = 1;
    return;
  }
  int mid = l + r >> 1;
  build(cur << 1, l, mid);
  build(cur << 1 | 1, mid + 1, r);
  pushup(cur);
}
void update(int cur, int l, int r, int vl, int vr, long long v) {
  if (l >= vl && r <= vr) {
    apply(cur, v);
    return;
  }
  pushdown(cur);
  int mid = l + r >> 1;
  if (mid >= vl) update(cur << 1, l, mid, vl, vr, v);
  if (mid < vr) update(cur << 1 | 1, mid + 1, r, vl, vr, v);
  pushup(cur);
}
}  // namespace Segtree
void dfs1(int x, int p) {
  par[x] = p;
  sz[x] = 1;
  for (int i = 0; i < int(edge[x].size()); i++) {
    int y = edge[x][i];
    dfs1(y, x);
    sz[x] += sz[y];
    if (sz[y] > sz[son[x]]) son[x] = y;
  }
}
void dfs2(int x, int t) {
  top[x] = t;
  dfn[x] = ++k;
  if (son[x]) dfs2(son[x], t);
  for (int i = 0; i < int(edge[x].size()); i++) {
    int y = edge[x][i];
    if (y == son[x]) continue;
    dfs2(y, y);
  }
}
int main() {
  scanf("%d%d%d%d", &n, &m, &q, &c);
  for (int i = 1; i <= n; i++) {
    scanf("%d", &a[i]);
    eve[a[i]].push_back(make_pair(i, 1));
  }
  for (int i = 2; i <= n; i++) {
    int p;
    scanf("%d", &p);
    edge[p].push_back(i);
  }
  dfs1(1, 0);
  dfs2(1, 1);
  for (int i = 1; i <= m; i++) scanf("%d", &b[i]);
  for (int i = 1; i <= q; i++) {
    int op;
    scanf("%d", &op);
    if (op == 1) {
      int x, w;
      scanf("%d%d", &x, &w);
      eve[a[x]].push_back(make_pair(x, -1));
      a[x] = w;
      eve[a[x]].push_back(make_pair(x, 1));
      ans[i] = -1;
    } else {
      int k;
      scanf("%d", &k);
      eve[k].push_back(make_pair(i, 0));
    }
  }
  Segtree::build(1, 1, n);
  for (int i = 1; i <= m; i++) {
    for (int j = 0; j < int(eve[i].size()); j++) {
      int x = eve[i][j].first, f = eve[i][j].second;
      if (f == 0) {
        long long val0 = Segtree::val[1][0], val1 = Segtree::val[1][1],
                  val2 = Segtree::val[1][2];
        ans[x] = val0 * c * c - 2 * c * val1 * b[i] + val2 * b[i] * b[i];
      } else {
        while (x) {
          Segtree::update(1, 1, n, dfn[top[x]], dfn[x], f);
          x = par[top[x]];
        }
      }
    }
    for (int j = 0; j < int(eve[i].size()); j++) {
      int x = eve[i][j].first, f = eve[i][j].second;
      if (f != 0) {
        while (x) {
          Segtree::update(1, 1, n, dfn[top[x]], dfn[x], -f);
          x = par[top[x]];
        }
      }
    }
  }
  for (int i = 1; i <= q; i++)
    if (ans[i] >= 0) printf("%.10lf\n", double(ans[i]) / double(n));
  return 0;
}
