#include <bits/stdc++.h>
using namespace std;
const int nmax = 5e4;
const int logmax = 18;
const int base = 666013;
int n, m, q;
int col[nmax + 1];
long long C, cost[nmax + 1];
vector<int> g[nmax + 1];
bool used[nmax + 1], viz[nmax + 1];
int father[nmax + 1];
int height[nmax + 1], weight[nmax + 1], wmax[nmax + 1];
int nr_nodes;
int nodes_in_comp[nmax + 1];
int last_cen[nmax + 1];
int color_count[nmax + 1];
long long sum_heights[nmax + 1], sum_distances[nmax + 1];
int anc[logmax + 1][nmax + 1];
unordered_map<int, long long> all_dist[nmax + 1], dist_to_last[nmax + 1];
unordered_map<int, int> partial_count[nmax + 1], Distance[nmax + 1];
void read_input() {
  fscanf(stdin, "%d%d%d%I64d", &n, &m, &q, &C);
  for (int i = 1; i <= n; ++i) fscanf(stdin, "%d", &col[i]);
  for (int i = 2; i <= n; ++i) {
    int x;
    fscanf(stdin, "%d", &x);
    g[x].push_back(i);
    g[i].push_back(x);
  }
  for (int i = 1; i <= m; ++i) fscanf(stdin, "%I64d", &cost[i]);
}
void initial_dfs(int node) {
  viz[node] = 1;
  for (auto i : g[node]) {
    if (viz[i] == 0) {
      height[i] = height[node] + 1;
      father[i] = node;
      initial_dfs(i);
    }
  }
}
void dfs(int node) {
  nodes_in_comp[nr_nodes++] = node;
  viz[node] = 1;
  weight[node] = 1;
  wmax[node] = 0;
  for (auto i : g[node]) {
    if (viz[i] == 0 && used[i] == 0) {
      dfs(i);
      weight[node] += weight[i];
      wmax[node] = max(wmax[node], weight[i]);
    }
  }
}
int centroid_decomp(int node) {
  nr_nodes = 0;
  dfs(node);
  int centroid = -1;
  for (int i = 0; i < nr_nodes; ++i) {
    int x = nodes_in_comp[i];
    if (nr_nodes - weight[x] <= nr_nodes / 2 && wmax[x] <= nr_nodes / 2) {
      centroid = x;
    }
    viz[x] = 0;
  }
  used[centroid] = 1;
  for (auto i : g[centroid]) {
    if (used[i] == 0) {
      int next_centroid = centroid_decomp(i);
      last_cen[next_centroid] = centroid;
    }
  }
  return centroid;
}
int find_distance(int x, int y) {
  int ans = height[x] + height[y];
  if (height[x] > height[y]) swap(x, y);
  int dif = height[y] - height[x];
  for (int i = logmax; i >= 0; --i)
    if (dif & (1 << i)) y = anc[i][y];
  for (int i = logmax; i >= 0; --i) {
    if (anc[i][x] != anc[i][y]) {
      x = anc[i][x];
      y = anc[i][y];
    }
  }
  if (x != y) x = anc[0][x];
  return ans - 2 * height[x];
}
void precalculate() {
  height[1] = 1;
  initial_dfs(1);
  memset(viz, 0, sizeof(viz));
  centroid_decomp(1);
  for (int i = 1; i <= n; ++i) anc[0][i] = father[i];
  for (int i = 1; (1 << i) <= n; ++i)
    for (int j = 1; j <= n; ++j) anc[i][j] = anc[i - 1][anc[i - 1][j]];
  for (int i = 1; i <= n; ++i) {
    int ancestor = i;
    while (ancestor != 0) {
      Distance[i][ancestor] = find_distance(i, ancestor);
      ancestor = last_cen[ancestor];
    }
  }
}
void update_color(int x, int color, int type) {
  sum_distances[color] += type * all_dist[color][x];
  int u = x;
  while (last_cen[u] != 0) {
    int CEN = last_cen[u];
    sum_distances[color] +=
        type * Distance[x][CEN] *
        (partial_count[color][CEN] - partial_count[color][u]);
    sum_distances[color] +=
        type * (all_dist[color][CEN] - dist_to_last[color][u]);
    u = CEN;
  }
  u = x;
  while (u != 0) {
    partial_count[color][u] += type;
    all_dist[color][u] += type * Distance[x][u];
    dist_to_last[color][u] += type * Distance[x][last_cen[u]];
    u = last_cen[u];
  }
  sum_heights[color] += type * height[x];
  color_count[color] += type;
}
int main() {
  read_input();
  precalculate();
  for (int i = 1; i <= n; ++i) update_color(i, col[i], 1);
  while (q--) {
    int type;
    fscanf(stdin, "%d", &type);
    if (type == 1) {
      int node, new_color;
      fscanf(stdin, "%d%d", &node, &new_color);
      update_color(node, col[node], -1);
      update_color(node, new_color, 1);
      col[node] = new_color;
    } else {
      int k;
      fscanf(stdin, "%d", &k);
      long long e1 = sum_heights[k];
      long long e2 = sum_heights[k] * color_count[k] - sum_distances[k];
      long long aux = e2 * cost[k] * cost[k] - e1 * 2 * C * cost[k];
      fprintf(stdout, "%.12lf\n", (double)aux / n + C * C);
    }
  }
  return 0;
}
