#include <bits/stdc++.h>
using namespace std;
int N, M, Q, C;
int F[50005], Log[50005];
int TT[50005];
vector<int> G[50005];
int Cost[50005], Level[50005];
bool Blocked[50005];
int P[50005], Sz[50005];
struct Elem {
  long long A, B;
  int H;
};
unordered_map<int, Elem> X[50005];
int Father[22][50005];
long long Dist[50005], Sum[50005];
int Cnt[50005];
void Read() {
  scanf("%d%d%d%d", &N, &M, &Q, &C);
  for (int i = 1; i <= N; i++) {
    scanf("%d", &F[i]);
    Cnt[F[i]]++;
  }
  for (int i = 2; i <= N; i++) {
    int p;
    scanf("%d", &p);
    TT[i] = p;
    Father[0][i] = p;
    G[p].push_back(i);
    G[i].push_back(p);
  }
  for (int i = 1; i <= M; i++) scanf("%d", &Cost[i]);
}
void precalcLog() {
  for (int i = 2; i <= N; i++) Log[i] = Log[i / 2] + 1;
}
void precalcFather() {
  for (int i = 1; i <= Log[N]; i++)
    for (int j = 1; j <= N; j++) Father[i][j] = Father[i - 1][Father[i - 1][j]];
}
int Anc(int x, int dist) {
  while (dist > 0) {
    int k = Log[dist];
    x = Father[k][x];
    dist -= (1 << k);
  }
  return x;
}
int Distance(int x, int y) {
  int initx = x, inity = y;
  if (Level[x] > Level[y]) swap(x, y);
  y = Anc(y, Level[y] - Level[x]);
  int lca;
  if (x == y)
    lca = x;
  else {
    for (int k = Log[N]; k >= 0; k--)
      if (Father[k][x] != Father[k][y]) {
        x = Father[k][x];
        y = Father[k][y];
      }
    lca = Father[0][x];
  }
  return Level[initx] + Level[inity] - 2 * Level[lca];
}
void DFS(int node, int father) {
  Level[node] = Level[father] + 1;
  for (int i = 0; i < G[node].size(); i++) {
    int neighb = G[node][i];
    if (neighb == father) continue;
    DFS(neighb, node);
  }
}
void DFS2(int node, int father) {
  Sz[node] = 1;
  for (int i = 0; i < G[node].size(); i++) {
    int neighb = G[node][i];
    if (neighb == father || Blocked[neighb] == 1) continue;
    DFS2(neighb, node);
    Sz[node] += Sz[neighb];
  }
}
int findCentroid(int node, int father, int sz) {
  for (int i = 0; i < G[node].size(); i++) {
    int neighb = G[node][i];
    if (neighb == father || Blocked[neighb] == 1) continue;
    if (Sz[neighb] > sz / 2) return findCentroid(neighb, node, sz);
  }
  return node;
}
void build() {
  for (int i = 1; i <= N; i++) {
    int color = F[i];
    int node = i;
    Sum[color] += Level[i];
    int nr = 0;
    while (node != 0) {
      ++nr;
      Elem &curr = X[node][color];
      int father = P[node];
      if (father != 0) {
        Elem &prev = X[father][color];
        int d = Distance(i, father);
        Dist[color] += 1LL * d * (prev.H - curr.H);
        Dist[color] += prev.A - curr.B;
        curr.B += d;
      }
      curr.H++;
      int dist = Distance(i, node);
      curr.A += dist;
      node = father;
    }
    node = i;
    Dist[color] += X[i][color].A;
  }
}
void Update(int node, int c) {
  int color = F[node];
  F[node] = c;
  Cnt[color]--;
  Cnt[c]++;
  Sum[color] -= Level[node];
  Sum[c] += Level[node];
  int i = node;
  Dist[color] -= X[node][color].A;
  while (node != 0) {
    Elem &curr = X[node][color];
    int father = P[node];
    if (father != 0) {
      Elem &prev = X[father][color];
      int d = Distance(i, father);
      Dist[color] -= 1LL * d * (prev.H - curr.H);
      Dist[color] -= prev.A - curr.B;
      curr.B -= d;
    }
    curr.H--;
    int dist = Distance(i, node);
    curr.A -= dist;
    if (curr.H == 0) {
      X[node].erase(color);
    }
    node = father;
  }
  node = i;
  color = c;
  Dist[color] += X[i][color].A;
  while (node != 0) {
    Elem &curr = X[node][color];
    int father = P[node];
    if (father != 0) {
      Elem &prev = X[father][color];
      int d = Distance(i, father);
      Dist[color] += 1LL * d * (prev.H - curr.H);
      Dist[color] += prev.A - curr.B;
      curr.B += d;
    }
    curr.H++;
    int dist = Distance(i, node);
    curr.A += dist;
    node = father;
  }
}
void Query(int color) {
  double ans = (double)C * (double)C;
  ans -= (2.0 * C * Cost[color] * (Sum[color])) / (double)N;
  double aux = -Dist[color];
  aux += (Cnt[color]) * Sum[color];
  ans += (1.0 * Cost[color] * Cost[color] * aux) / (double)N;
  printf("%.12f\n", ans);
}
void Decomposition(int root, int father) {
  DFS2(root, 0);
  int centroid = findCentroid(root, 0, Sz[root]);
  Blocked[centroid] = 1;
  P[centroid] = father;
  for (int i = 0; i < G[centroid].size(); i++) {
    int neighb = G[centroid][i];
    if (Blocked[neighb] == 1 || neighb == father) continue;
    Decomposition(neighb, centroid);
  }
}
int main() {
  Read();
  precalcLog();
  precalcFather();
  DFS(1, 0);
  Decomposition(1, 0);
  build();
  for (int i = 1; i <= Q; i++) {
    int type, x, y;
    scanf("%d", &type);
    if (type == 1) {
      scanf("%d%d", &x, &y);
      Update(x, y);
    } else {
      scanf("%d", &x);
      Query(x);
    }
  }
  return 0;
}
