#include <bits/stdc++.h>   using namespace std;   using Int = long long;   template <class T1, class T2>   ostream &operator<<(ostream &os, const pair<T1, T2> &a) {     return os <<  (  << a.first <<  ,   << a.second <<  ) ;   };   template <class T>   void pv(T a, T b) {     for (T i = a; i != b; ++i) cerr << *i <<    ;     cerr << endl;   }   template <class T>   bool chmin(T &t, const T &f) {     if (t > f) {       t = f;       return true;     }     return false;   }   template <class T>   bool chmax(T &t, const T &f) {     if (t < f) {       t = f;       return true;     }     return false;   }   template <class T, class S, class OpTT, class OpST, class OpSS>   struct SegmentTree {     const OpTT opTT;     const OpST opST;     const OpSS opSS;     const T idT;     const S idS;     int n;     vector<T> ts;     vector<S> ss;     SegmentTree(int n_, const OpTT opTT, const OpST opST, const OpSS opSS,                 const T &idT, const S &idS)         : opTT(opTT), opST(opST), opSS(opSS), idT(idT), idS(idS) {       for (n = 1; n < n_; n <<= 1) {       }       ts.assign(n << 1, idT);       ss.assign(n << 1, idS);     }     T &at(int a) { return ts[n + a]; }     void build() {       for (int a = n; --a;) ts[a] = opTT(ts[a << 1], ts[a << 1 | 1]);     }     T query(int a, int b, const S &s) { return query(1, 0, n, a, b, s); }       private:     T query(int u, int l, int r, int a, int b, const S &s) {       if (a < l) a = l;       if (b > r) b = r;       if (a >= b) return idT;       if (a == l && b == r) {         ts[u] = opST(s, ts[u], r - l);         ss[u] = opSS(s, ss[u]);         return ts[u];       }       const int uL = u << 1, uR = u << 1 | 1;       const int mid = (l + r) >> 1;       {         ts[uL] = opST(ss[u], ts[uL], mid - l);         ts[uR] = opST(ss[u], ts[uR], r - mid);         ss[uL] = opSS(ss[u], ss[uL]);         ss[uR] = opSS(ss[u], ss[uR]);         ss[u] = idS;       }       const T resL = query(uL, l, mid, a, b, s);       const T resR = query(uR, mid, r, a, b, s);       ts[u] = opTT(ts[uL], ts[uR]);       return opTT(resL, resR);     }   };   constexpr int MAX = 50005;   int N, M, Q, C;   int F[MAX], P[MAX];   int D[MAX];   int T[MAX], X[MAX], K[MAX];   double anss[MAX];   int f[MAX];   int queriesLen;   pair<pair<int, int>, pair<int, int>> queries[4 * MAX];   Int vals[MAX];   void brute() {     fill(vals, vals + N, 0);     Int s1 = 0, s2 = 0;     for (int h = 0; h < queriesLen; ++h) {       switch (queries[h].second.second) {         case +1: {           const int u = queries[h].second.first;           for (int v = u; v != -1; v = P[v]) {             ++s1;             s2 += vals[v];           }           for (int v = u; v != -1; v = P[v]) {             ++vals[v];           }         } break;         case -1: {           const int u = queries[h].second.first;           for (int v = u; v != -1; v = P[v]) {             --vals[v];           }           for (int v = u; v != -1; v = P[v]) {             --s1;             s2 -= vals[v];           }         } break;         case 0: {           const int k = queries[h].first.first;           double ans = 0.0;           ans += 1.0 * C * C * N;           ans -= 2.0 * C * D[k] * s1;           ans += 1.0 * D[k] * D[k] * (s1 + 2.0 * s2);           ans /= N;           anss[queries[h].second.first] = ans;         } break;         default:           assert(false);       }     }     for (int q = 0; q < Q; ++q) {       if (T[q] == 2) {         printf( %.10f n , anss[q]);       }     }   }   vector<int> G[MAX];   int par[MAX], sz[MAX], dep[MAX];   int O, ord[MAX], head[MAX];   void dfs0(int u, int p) {     par[u] = p;     sz[u] = 1;     dep[u] = (p == -1) ? 0 : (dep[p] + 1);     for (const int v : G[u]) {       if (v != p) {         dfs0(v, u);         sz[u] += sz[v];       }     }   }   void dfs1(int u, int p, int h) {     ord[u] = O++;     head[u] = h;     int vm = -1;     for (const int v : G[u]) {       if (v != p) {         if (vm == -1 || sz[vm] < sz[v]) {           vm = v;         }       }     }     if (vm != -1) {       dfs1(vm, u, h);       for (const int v : G[u]) {         if (v != p && v != vm) {           dfs1(v, u, v);         }       }     }   }   void solve() {     for (int u = 0; u < N; ++u) {       G[u].clear();     }     for (int u = 1; u < N; ++u) {       G[P[u]].push_back(u);     }     const int rt = 0;     dfs0(rt, -1);     O = 0;     dfs1(rt, -1, 0);     auto opTT = [](Int t0, Int t1) { return t0 + t1; };     auto opST = [](Int s, Int t, Int sz) { return t + s * sz; };     auto opSS = [](Int s0, Int s1) { return s0 + s1; };     SegmentTree<Int, Int, decltype(opTT), decltype(opST), decltype(opSS)> seg(         N, opTT, opST, opSS, 0, 0);     auto query = [&](int u, int val) {       Int ret = 0;       for (; u != -1;) {         const Int h = head[u];         ret += seg.query(ord[h], ord[u] + 1, val);         u = par[h];       }       return ret;     };     Int s1 = 0, s2 = 0;     for (int h = 0; h < queriesLen; ++h) {       switch (queries[h].second.second) {         case +1: {           const int u = queries[h].second.first;           s1 += (dep[u] + 1);           s2 += query(u, 0);           query(u, +1);         } break;         case -1: {           const int u = queries[h].second.first;           s1 -= (dep[u] + 1);           s2 -= query(u, -1);         } break;         case 0: {           const int k = queries[h].first.first;           double ans = 0.0;           ans += 1.0 * C * C * N;           ans -= 2.0 * C * D[k] * s1;           ans += 1.0 * D[k] * D[k] * (s1 + 2.0 * s2);           ans /= N;           anss[queries[h].second.first] = ans;         } break;         default:           assert(false);       }     }     for (int q = 0; q < Q; ++q) {       if (T[q] == 2) {         printf( %.10f n , anss[q]);       }     }   }   int main() {     for (; ~scanf( %d%d%d%d , &N, &M, &Q, &C);) {       for (int u = 0; u < N; ++u) {         scanf( %d , &F[u]);         --F[u];       }       P[0] = -1;       for (int u = 1; u < N; ++u) {         scanf( %d , &P[u]);         --P[u];       }       for (int k = 0; k < M; ++k) {         scanf( %d , &D[k]);       }       for (int q = 0; q < Q; ++q) {         scanf( %d , &T[q]);         if (T[q] == 1) {           scanf( %d , &X[q]);           --X[q];         }         scanf( %d , &K[q]);         --K[q];       }       copy(F, F + N, f);       queriesLen = 0;       for (int u = 0; u < N; ++u) {         queries[queriesLen++] = {{f[u], -1}, {u, +1}};       }       for (int q = 0; q < Q; ++q) {         if (T[q] == 1) {           const int u = X[q];           queries[queriesLen++] = {{f[u], q}, {u, -1}};           f[u] = K[q];           queries[queriesLen++] = {{f[u], q}, {u, +1}};         } else {           queries[queriesLen++] = {{K[q], q}, {q, 0}};         }       }       for (int u = 0; u < N; ++u) {         queries[queriesLen++] = {{f[u], Q}, {u, -1}};       }       sort(queries, queries + queriesLen);       solve();     }     return 0;   }