#include <algorithm>
#include <cstdio>
#include <set>
#include <vector>
#define pli pair<long long, int>
#define N_ 201000
using namespace std;
vector<int> E[N_], L[N_];
int X[N_], n, C[N_], chk[N_];
long long D[N_], dis[N_][20], INF = 4e18;
int Root[N_][20];
vector<int> TP;

multiset<long long> On[N_];
set<pli> Off[N_], Set;
bool MST[N_];

void DFS(int a, int pp) {
  int i;
  TP.push_back(a);
  C[a] = 1;
  for (i = 0; i < E[a].size(); i++) {
    if (chk[E[a][i]] || E[a][i] == pp)
      continue;
    D[E[a][i]] = D[a] + L[a][i];
    DFS(E[a][i], a);
    C[a] += C[E[a][i]];
  }
}
void Do(int a, int dep) {
  int i;
  D[a] = 0;
  TP.clear();
  DFS(a, 0);
  if (C[a] == 1)
    return;
  int M = C[a] + 1, mid = 0;
  for (i = 0; i < TP.size(); i++) {
    if (C[a] < C[TP[i]] * 2 && M > C[TP[i]]) {
      M = C[TP[i]];
      mid = TP[i];
    }
  }
  chk[mid] = 1;
  for (i = 0; i < E[mid].size(); i++) {
    if (!chk[E[mid][i]]) {
      Do(E[mid][i], dep + 1);
    }
  }
  chk[mid] = 0;
  TP.clear();
  D[mid] = 0;
  DFS(mid, 0);
  for (i = 0; i < TP.size(); i++) {
    Root[TP[i]][dep] = mid;
    dis[TP[i]][dep] = D[TP[i]];
    Off[mid].insert({D[TP[i]] + X[TP[i]], TP[i]});
  }

  Off[mid].insert({INF, -1});
  On[mid].insert(INF);
  Set.insert(
      {Off[mid].begin()->first + *On[mid].begin(), Off[mid].begin()->second});
}

void Make(int a) {
  MST[a] = true;
  int i;
  for (i = 0; i < 20; i++) {
    if (!Root[a][i])
      break;
    int rt = Root[a][i];
    pli r1 = {Off[rt].begin()->first + *On[rt].begin(),
              Off[rt].begin()->second};
    Off[rt].erase({dis[a][i] + X[a], a});
    On[rt].insert(dis[a][i] + X[a]);
    pli r2 = {Off[rt].begin()->first + *On[rt].begin(),
              Off[rt].begin()->second};
    Set.erase(r1);
    Set.insert(r2);
  }
}

int main() {
  int i, a, b, c;
  scanf("%d", &n);
  for (i = 1; i <= n; i++) {
    scanf("%d", &X[i]);
  }
  for (i = 1; i < n; i++) {
    scanf("%d%d%d", &a, &b, &c);
    E[a].push_back(b);
    L[a].push_back(c);
    E[b].push_back(a);
    L[b].push_back(c);
  }
  Do(1, 0);

  Make(1);
  long long res = 0;
  for (int i = 0; i < n - 1; i++) {
    pli tp = *Set.begin();
    res += tp.first;
    Make(tp.second);
  }
  printf("%lld\\n", res);
}

/*#include<cstdio>
#include<algorithm>
using namespace std;
int w[101000];
int n;
int main(){
    int i;

  //  freopen("/Users/joseunghyeon/Downloads/in (2)/eval_input.txt","r",stdin);
    int TC, TT;
    scanf("%d",&TC);
    for(TT=1;TT<=TC;TT++){
        scanf("%d",&n);
        for(i=1;i<=n;i++)scanf("%d",&w[i]);
        sort(w+1,w+n+1);
        printf("Case #%d\\n",TT);
        if(w[n]-w[1]>1){
            printf("No\\n");
            continue;
        }
        if(w[n]-w[1]==0){
            if(w[1] <= n/2 || w[1] == n-1)printf("Yes\\n");
            else printf("No\\n");
            continue;
        }
        for(i=1;i<n;i++)if(w[i]!=w[i+1])break;
        int t = i;
        if(t + 1 <= w[n] && t + (n-t)/2 >= w[n])printf("Yes\\n");
        else printf("No\\n");
    }
}
*/

/*#include<cstdio>
#include<algorithm>
using namespace std;
int n, w[201000];
int main(){
    char fp[200];

    int T[2]={6,18};
    freopen("/Users/joseunghyeon/Downloads/in (2)/eval_input.txt","w",stdout);
    printf("%d\\n",T[0]+T[1]);
    for(int TTT = 0; TTT < 2; TTT++){
        for(int TT=0;TT< T[TTT];TT++){
            fprintf(stderr,"%d %d\\n",TTT,TT);
            sprintf(fp, "/Users/joseunghyeon/Downloads/in (2)/%d_%02d.txt", TTT,
TT); freopen(fp, "r",stdin); int n, a; scanf("%d",&n); printf("%d\\n",n); for(int
i=0;i<n;i++){ scanf("%d",&a); printf("%d",a); if(i!=n-1)printf(" ");
            }
            printf("\\n");
        }
    }
    return 0;
}
*/

/*#include<cstdio>
#include<algorithm>
using namespace std;
int n, w[201000];
int main(){
    char fp[200];
    int TC = 0;
    int T[2]={6,18};
    freopen("/Users/joseunghyeon/Downloads/out (2)/eval_output.txt","w",stdout);
    for(int TTT = 0; TTT < 2; TTT++){
        for(int TT=0;TT< T[TTT];TT++){
            fprintf(stderr,"%d %d\\n",TTT,TT);
            sprintf(fp, "/Users/joseunghyeon/Downloads/out (2)/%d_%02d.txt",
TTT, TT); freopen(fp, "r",stdin); char rr[10]; scanf("%s",rr); printf("Case
#%d\\n%s\\n",++TC,rr);
        }
    }
    return 0;
}*/

/*
#include<algorithm>
#include<cstdio>
#include<map>
#include<vector>
using namespace std;
map<vector<int>,int>Map;
vector<int> Do(vector<int>T){
    vector<int>ret,T1,T2;
    if(T.size()==1){
        ret.push_back(T[0]+1);
        return ret;
    }
    int i;
    for(i=0;i<T.size()/2;i++){
        T1.push_back(min(T[i*2],T[i*2+1]));
        T2.push_back(max(T[i*2],T[i*2+1]));
    }
    vector<int>r1, r2;
    r1 = Do(T1);
    r2 = Do(T2);
    for(i=0;i<r1.size();i++)ret.push_back(r1[i]);
    for(i=0;i<r2.size();i++)ret.push_back(r2[i]);
    return ret;
}
int main(){
    int i, w[8];
    vector<int>TP(8);
    vector<int>res;
    for(i=0;i<8;i++)w[i]=i;
    do{
        for(i=0;i<8;i++)TP[i]=w[i];
        res = Do(TP);
        Map[res]  = 1;
    }while(next_permutation(w,w+8));
    for(auto &tp : Map){
        for(i=0;i<8;i++)printf("%d ",tp.first[i]);
        printf("\\n");
    }
}*/

#include <algorithm>
#include <cstdio>
#include <set>
#include <vector>
#define pli pair<long long, int>
#define N_ 201000
using namespace std;
vector<int> E[N_], L[N_];
int X[N_], n, C[N_], chk[N_], Num[N_][20];
long long D[N_], dis[N_][20], INF = 4e18;
int Root[N_][20];
vector<int> TP;
vector<pli> U[N_];
set<pli> Set;

int PV[N_], Mn[N_];
long long RR[N_];

bool MST[N_];

void DFS(int a, int pp) {
  int i;
  TP.push_back(a);
  C[a] = 1;
  for (i = 0; i < E[a].size(); i++) {
    if (chk[E[a][i]] || E[a][i] == pp)
      continue;
    D[E[a][i]] = D[a] + L[a][i];
    DFS(E[a][i], a);
    C[a] += C[E[a][i]];
  }
}
void Do(int a, int dep) {
  int i;
  D[a] = 0;
  TP.clear();
  DFS(a, 0);
  if (C[a] == 1)
    return;
  int M = C[a] + 1, mid = 0;
  for (i = 0; i < TP.size(); i++) {
    if (C[a] < C[TP[i]] * 2 && M > C[TP[i]]) {
      M = C[TP[i]];
      mid = TP[i];
    }
  }
  chk[mid] = 1;
  for (i = 0; i < E[mid].size(); i++) {
    if (!chk[E[mid][i]]) {
      Do(E[mid][i], dep + 1);
    }
  }
  chk[mid] = 0;
  TP.clear();
  D[mid] = 0;
  DFS(mid, 0);
  for (i = 0; i < TP.size(); i++) {
    Root[TP[i]][dep] = mid;
    dis[TP[i]][dep] = D[TP[i]];
    U[mid].push_back({D[TP[i]] + X[TP[i]], TP[i]});
  }
  sort(U[mid].begin(), U[mid].end());
  for (i = 0; i < U[mid].size(); i++) {
    Num[U[mid][i].second][dep] = i;
  }
  RR[mid] = INF;
  Mn[mid] = U[mid].size();
}

void Make(int a) {
  MST[a] = true;
  int i;
  for (i = 0; i < 20; i++) {
    if (!Root[a][i])
      break;
    int rt = Root[a][i], sz = U[rt].size();
    if (PV[rt] != sz && Mn[rt] != sz) {
      Set.erase(
          {U[rt][Mn[rt]].first + U[rt][PV[rt]].first, U[rt][PV[rt]].second});
    }
    Mn[rt] = min(Mn[rt], Num[a][i]);
    while (PV[rt] < sz && MST[U[rt][PV[rt]].second])
      PV[rt]++;
    if (PV[rt] != sz && Mn[rt] != sz) {
      Set.insert(
          {U[rt][Mn[rt]].first + U[rt][PV[rt]].first, U[rt][PV[rt]].second});
    }
  }
}

int main() {
  int i, a, b, c;
  scanf("%d", &n);
  for (i = 1; i <= n; i++) {
    scanf("%d", &X[i]);
  }
  for (i = 1; i < n; i++) {
    scanf("%d%d%d", &a, &b, &c);
    E[a].push_back(b);
    L[a].push_back(c);
    E[b].push_back(a);
    L[b].push_back(c);
  }
  Do(1, 0);

  Make(1);
  long long res = 0;
  for (int i = 0; i < n - 1; i++) {
    pli tp = *Set.begin();
    res += tp.first;
    Make(tp.second);
  }
  printf("%lld\\n", res);
}


#include <algorithm>
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <map>
#include <set>
#include <vector>

#define MIN_INT -2147483648
#define MAX_INT 2147483647
#define MIN_LONG -9223372036854775808L
#define MAX_LONG 9223372036854775807L
#define PI 3.141592653589793238462643383279502884L

#define MOD 1000000007L

#define long long long int

using std::cerr;
using std::cin;
using std::cout;
using std::map;
using std::pair;
using std::string;
using std::vector;

long max(long a, long b) { return a > b ? a : b; }

long min(long a, long b) { return a < b ? a : b; }

// @author: pashka
int main() {
  std::ios::sync_with_stdio(false);

  long b[3], d;
  cin >> b[0] >> b[1] >> b[2] >> d;

  long x[4] = {0, 0, 0};
  long l[4] = {0, 0, 0};
  long r[4] = {0, 0, 0};

  bool g[3];

  for (int i = 0; i < 3; i++) {
    g[i] = (b[i] - 1 > d);
  }

  int ng = 0;
  for (int i = 0; i < 3; i++) {
    if (g[i])
      ng++;
  }

  long res = 1;
  for (int i = 0; i < 3; i++)
    if (g[i]) {
      r[i] = min(b[i], d + 1);
      res *= r[i];
      res %= MOD;
    }

  if (ng > 0)
    while (true) {
      //            cout << x[0] << " " << x[1] << " " << x[2] << " " << res <<
      //            "\\n";
      bool ok = true;
      for (int i = 0; i < 3; i++) {
        if (x[i] < b[i] - 1) {
          ok = false;
        }
      }
      if (ok)
        break;

      ok = true;
      for (int i = 0; i < 3; i++) {
        if (g[i] && (l[i] != x[i] - d || r[i] != x[i] + d + 1)) {
          ok = false;
        }
      }
      if (ok) {

        //                cout << x[0] << " " << x[1] << " " << x[2] << "\\n";

        long dd = 2 * d + 1;

        long d2 = 1;
        for (int i = 0; i < ng - 1; i++) {
          d2 = (d2 * dd) % MOD;
        }
        long sx = 0;
        for (int i = 0; i < 3; i++) {
          if (g[i])
            sx += x[i];
        }

        long ss = (d2 * (dd + sx)) % MOD;
        long e = (ss - res) % MOD;

        //                cout << d2 << " " << sx << " " << ss << " " << e <<
        //                "\\n";

        if (e < 0)
          e += MOD;

        sx = 0;
        for (int i = 0; i < 3; i++) {
          if (g[i])
            sx += b[i] - 1;
          sx %= MOD;
        }
        ss = (d2 * (dd + sx)) % MOD;

        res = ss - 2 * e;
        while (res < 0) {
          res += MOD;
        }

        //                cout << ss << " " << res << "\\n";
        break;
      }

      bool c[3] = {true, true, true};
      for (int i = 0; i < 3; i++) {
        for (int j = i + 1; j < 3; j++) {
          if ((x[i] + 1) * b[j] > (x[j] + 1) * b[i]) {
            c[i] = false;
          } else {
            c[j] = false;
          }
        }
      }

      //        cout << c[0] << " " << c[1] << " " << c[2] << "\\n";

      ok = false;
      for (int i = 0; i < 3; i++) {
        if (c[i]) {
          ok = true;
          x[i]++;
          if (g[i] && x[i] + d < b[i]) {
            long s = 1;
            for (int j = 0; j < 3; j++)
              if (g[j] && i != j) {
                s *= (r[j] - l[j]);
              }
            res += s;
            while (res >= MOD) {
              res -= MOD;
            }
          }
          l[i] = max(x[i] - d, 0);
          r[i] = min(x[i] + d + 1, b[i]);
        }
      }
      if (!ok) {
        return 1;
      }
    }
  else
    res = 1;

  for (int i = 0; i < 3; i++) {
    if (!g[i]) {
      res *= b[i];
      res %= MOD;
    }
  }

  cout << res << "\\n";

  return 0;
}

#include <algorithm>
#include <cstdio>
#include <iomanip>
#include <iostream>
#include <map>
#include <set>
#include <vector>

#define MIN_INT -2147483648
#define MAX_INT 2147483647
#define MIN_LONG -9223372036854775808L
#define MAX_LONG 9223372036854775807L
#define PI 3.141592653589793238462643383279502884L

#define MOD 1000000007L

#define long long long int

using std::cerr;
using std::cin;
using std::cout;
using std::map;
using std::pair;
using std::string;
using std::vector;

long max(long a, long b) { return a > b ? a : b; }

long min(long a, long b) { return a < b ? a : b; }

// @author: pashka
int main() {
  std::ios::sync_with_stdio(false);

  long b[3], d;
  cin >> b[0] >> b[1] >> b[2] >> d;

  long x[4] = {0, 0, 0};
  long l[4] = {0, 0, 0};
  long r[4] = {0, 0, 0};

  bool g[3];

  for (int i = 0; i < 3; i++) {
    g[i] = (b[i] - 1 > d);
  }

  int ng = 0;
  for (int i = 0; i < 3; i++) {
    if (g[i])
      ng++;
  }

  long res = 1;
  for (int i = 0; i < 3; i++)
    if (g[i]) {
      r[i] = min(b[i], d + 1);
      res *= r[i];
      res %= MOD;
    }

  if (ng > 0)
    while (true) {
      //            cout << x[0] << " " << x[1] << " " << x[2] << " " << res <<
      //            "\\n";
      bool ok = true;
      for (int i = 0; i < 3; i++) {
        if (x[i] < b[i] - 1) {
          ok = false;
        }
      }
      if (ok)
        break;

      ok = true;
      for (int i = 0; i < 3; i++) {
        if (g[i] && (l[i] != x[i] - d || r[i] != x[i] + d + 1)) {
          ok = false;
        }
      }
      if (ok) {

        //                cout << x[0] << " " << x[1] << " " << x[2] << "\\n";

        long dd = 2 * d + 1;

        long d2 = 1;
        for (int i = 0; i < ng - 1; i++) {
          d2 = (d2 * dd) % MOD;
        }
        long sx = 0;
        for (int i = 0; i < 3; i++) {
          if (g[i])
            sx += x[i];
        }

        long ss = (d2 * (dd + sx)) % MOD;
        long e = (ss - res) % MOD;

        //                cout << d2 << " " << sx << " " << ss << " " << e <<
        //                "\\n";

        if (e < 0)
          e += MOD;

        sx = 0;
        for (int i = 0; i < 3; i++) {
          if (g[i])
            sx += b[i] - 1;
          sx %= MOD;
        }
        ss = (d2 * (dd + sx)) % MOD;

        res = ss - 2 * e;
        while (res < 0) {
          res += MOD;
        }

        //                cout << ss << " " << res << "\\n";
        break;
      }

      bool c[3] = {true, true, true};
      for (int i = 0; i < 3; i++) {
        for (int j = i + 1; j < 3; j++) {
          if ((x[i] + 1) * b[j] > (x[j] + 1) * b[i]) {
            c[i] = false;
          } else {
            c[j] = false;
          }
        }
      }

      //        cout << c[0] << " " << c[1] << " " << c[2] << "\\n";

      ok = false;
      for (int i = 0; i < 3; i++) {
        if (c[i]) {

          long L = 0;
          long R = b[i] - x[i];

          while (R > L + 1) {
            long M = (L + R) / 2;
            bool c[3] = {true, true, true};
            x[i] = x[i] + M;
            for (int i = 0; i < 3; i++) {
              for (int j = i + 1; j < 3; j++) {
                if ((x[i] + 1) * b[j] > (x[j] + 1) * b[i]) {
                  c[i] = false;
                } else {
                  c[j] = false;
                }
              }
            }
            x[i] = x[i] - M;
            if (c[i]) {
              L = M;
            } else {
              R = M;
            }
          }

          ok = true;
          if (g[i]) {
            long s = 1;
            for (int j = 0; j < 3; j++)
              if (g[j] && i != j) {
                s *= (r[j] - l[j]);
              }
            long q = min(R, b[i] - 1 - d - x[i]) % MOD;
            if (q > 0)
              res += (s * q) % MOD;
            while (res >= MOD) {
              res -= MOD;
            }
          }
          x[i] += R;
          l[i] = max(x[i] - d, 0);
          r[i] = min(x[i] + d + 1, b[i]);
        }
      }
      if (!ok) {
        return 1;
      }
    }
  else
    res = 1;

  for (int i = 0; i < 3; i++) {
    if (!g[i]) {
      res *= b[i];
      res %= MOD;
    }
  }

  cout << res << "\\n";

  return 0;
}


#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>

using namespace std;
typedef long long ll;
const int MOD = 1e9 + 7;
const int MAXN = 1000010;
int _w;

int a, b, c, d;

void bmax(int &a, int b) { a = b > a ? b : a; }
void bmin(int &a, int b) { a = b < a ? b : a; }
int calc(int x1, int x2, int y1, int y2, int z1, int z2) {
  if (x1 > a - 1 || y1 > b - 1 || z1 > c - 1 || x2 < 0 || y2 < 0 || z2 < 0)
    return 0;
  bmax(x1, 0), bmin(x1, a - 1), bmax(x2, 0), bmin(x2, a - 1);
  bmax(y1, 0), bmin(y1, b - 1), bmax(y2, 0), bmin(y2, b - 1);
  bmax(z1, 0), bmin(z1, c - 1), bmax(z2, 0), bmin(z2, c - 1);
  int x = x2 - x1 + 1, y = y2 - y1 + 1, z = z2 - z1 + 1;
  return int((ll)x * y % MOD * z % MOD);
}

void nextblock(int x, int y, int z, int &xx, int &yy, int &zz) {
  xx = x + 1;
  yy = int((ll)xx * b / a);
  zz = int((ll)xx * c / a);
  if (yy == y && zz == z)
    return;
  yy = y + 1;
  xx = int((ll)yy * a / b);
  zz = int((ll)yy * c / b);
  if (xx == x && zz == z)
    return;
  zz = z + 1;
  xx = int((ll)zz * a / c);
  yy = int((ll)zz * b / c);
  if (xx == x && yy == y)
    return;
  printf("nextblock(%d, %d, %d)\\n", x, y, z);
  assert(0);
}
bool test(int x, int y, int z, int xx, int yy, int zz) {
  return false;
  if (xx < x || yy < y || zz < z)
    return false;
  if ((x < d && xx != x) || (y < d && yy != y) || (z < d && zz != z) ||
      (xx >= a - 1 - d && xx != x) || (yy >= b - 1 - d && yy != y) ||
      (zz >= c - 1 - d && zz != z))
    return false;
  else
    return true;
}
void jumpx(int x, int y, int z, int &xx, int &yy, int &zz) {
  int low = x, high = a - 1;
  while (low < high) {
    int mid = (low + high + 1) >> 1;
    int tx = mid;
    int ty = int((ll)tx * b / a);
    int tz = int((ll)tx * c / a);
    if (test(x, y, z, tx, ty, tz))
      low = mid;
    else
      high = mid - 1;
  }
  int tx = low;
  int ty = int((ll)tx * b / a);
  int tz = int((ll)tx * c / a);
  bmax(xx, tx), bmax(yy, ty), bmax(zz, tz);
}
void jumpy(int x, int y, int z, int &xx, int &yy, int &zz) {
  int low = y, high = b - 1;
  while (low < high) {
    int mid = (low + high + 1) >> 1;
    int ty = mid;
    int tx = int((ll)ty * a / b);
    int tz = int((ll)ty * c / b);
    if (test(x, y, z, tx, ty, tz))
      low = mid;
    else
      high = mid - 1;
  }
  int ty = low;
  int tx = int((ll)ty * a / b);
  int tz = int((ll)ty * c / b);
  bmax(xx, tx), bmax(yy, ty), bmax(zz, tz);
}
void jumpz(int x, int y, int z, int &xx, int &yy, int &zz) {
  int low = z, high = c - 1;
  while (low < high) {
    int mid = (low + high + 1) >> 1;
    int tz = mid;
    int ty = int((ll)tz * b / c);
    int tx = int((ll)tz * a / c);
    if (test(x, y, z, tx, ty, tz))
      low = mid;
    else
      high = mid - 1;
  }
  int tz = low;
  int ty = int((ll)tz * b / c);
  int tx = int((ll)tz * a / c);
  bmax(xx, tx), bmax(yy, ty), bmax(zz, tz);
}
void jumpnext(int x, int y, int z, int &xx, int &yy, int &zz) {
  xx = x, yy = y, zz = z;
  jumpx(x, y, z, xx, yy, zz);
  jumpy(x, y, z, xx, yy, zz);
  jumpz(x, y, z, xx, yy, zz);
}

int x[MAXN], y[MAXN], z[MAXN], v[MAXN], sz;
bool checkend() {
  return x[sz - 1] == a - 1 && y[sz - 1] == b - 1 && z[sz - 1] == c - 1;
}
void solve() {
  x[sz] = y[sz] = z[sz] = 0;
  v[sz++] = calc(-d, d, -d, d, -d, d);
  while (!checkend()) {
    jumpnext(x[sz - 1], y[sz - 1], z[sz - 1], x[sz], y[sz], z[sz]);
    int xx = x[sz], yy = y[sz], zz = z[sz];
    // printf( "x = %d, y = %d, z = %d, (pre)\\n", xx, yy, zz );
    nextblock(xx, yy, zz, x[sz], y[sz], z[sz]);
    if (xx != x[sz]) {
      v[sz] = calc(x[sz] + d, x[sz] + d, y[sz] - d, y[sz] + d, z[sz] - d,
                   z[sz] + d);
    } else if (yy != y[sz]) {
      v[sz] = calc(x[sz] - d, x[sz] + d, y[sz] + d, y[sz] + d, z[sz] - d,
                   z[sz] + d);
    } else if (zz != z[sz]) {
      v[sz] = calc(x[sz] - d, x[sz] + d, y[sz] - d, y[sz] + d, z[sz] + d,
                   z[sz] + d);
    }
    // printf( "x = %d, y = %d, z = %d, sz = %d\\n", x[sz], y[sz], z[sz], sz );
    ++sz;
  }
  int ans = 0;
  for (int i = 1; i < sz; ++i) {
    ll cnt = (ll)x[i] - x[i - 1] + y[i] - y[i - 1] + z[i] - z[i - 1];
    ans = int((ans + cnt % MOD * v[i - 1]) % MOD);
  }
  printf("%d\\n", (ans + (d == 0)) % MOD);
}

int main() {
  _w = scanf("%d%d%d%d", &a, &b, &c, &d);
  solve();
  return 0;
}

#include <algorithm>
#include <cassert>
#include <cstdio>
#include <cstring>

using namespace std;
typedef long long ll;
const int MOD = 1e9 + 7;
const int MAXN = 1000010;
int _w;

int a, b, c, d;

void bmax(int &a, int b) { a = b > a ? b : a; }
void bmin(int &a, int b) { a = b < a ? b : a; }
int calc(int x1, int x2, int y1, int y2, int z1, int z2) {
  if (x1 > a - 1 || y1 > b - 1 || z1 > c - 1 || x2 < 0 || y2 < 0 || z2 < 0)
    return 0;
  bmax(x1, 0), bmin(x1, a - 1), bmax(x2, 0), bmin(x2, a - 1);
  bmax(y1, 0), bmin(y1, b - 1), bmax(y2, 0), bmin(y2, b - 1);
  bmax(z1, 0), bmin(z1, c - 1), bmax(z2, 0), bmin(z2, c - 1);
  int x = x2 - x1 + 1, y = y2 - y1 + 1, z = z2 - z1 + 1;
  return int((ll)x * y % MOD * z % MOD);
}
int calc2(int x, int y, int z, int xx, int yy, int zz) {
  if (xx != x) {
    return calc(x + d, x + d, y - d, y + d, z - d, z + d);
  } else if (yy != y) {
    return calc(x - d, x + d, y + d, y + d, z - d, z + d);
  } else if (zz != z) {
    return calc(x - d, x + d, y - d, y + d, z + d, z + d);
  }
  assert(0);
}

void nextblock(int x, int y, int z, int &xx, int &yy, int &zz) {
  xx = x + 1;
  yy = int((ll)xx * b / a);
  zz = int((ll)xx * c / a);
  if (yy == y && zz == z)
    return;
  yy = y + 1;
  xx = int((ll)yy * a / b);
  zz = int((ll)yy * c / b);
  if (xx == x && zz == z)
    return;
  zz = z + 1;
  xx = int((ll)zz * a / c);
  yy = int((ll)zz * b / c);
  if (xx == x && yy == y)
    return;
  printf("nextblock(%d, %d, %d)\\n", x, y, z);
  assert(0);
}

bool test(int x, int y, int z, int xx, int yy, int zz) {
  if (xx < x || yy < y || zz < z)
    return false;
  if ((x < d && xx != x) || (y < d && yy != y) || (z < d && zz != z) ||
      (xx >= a - 1 - d && xx != x) || (yy >= b - 1 - d && yy != y) ||
      (zz >= c - 1 - d && zz != z))
    return false;
  else
    return true;
}

void jumpx(int x, int y, int z, int &xx, int &yy, int &zz) {
  int low = x, high = a - 1;
  while (low < high) {
    int mid = (low + high + 1) >> 1;
    int tx = mid;
    int ty = int((ll)tx * b / a);
    int tz = int((ll)tx * c / a);
    if (test(x, y, z, tx, ty, tz))
      low = mid;
    else
      high = mid - 1;
  }
  int tx = low;
  int ty = int((ll)tx * b / a);
  int tz = int((ll)tx * c / a);
  bmax(xx, tx), bmax(yy, ty), bmax(zz, tz);
}

void jumpy(int x, int y, int z, int &xx, int &yy, int &zz) {
  int low = y, high = b - 1;
  while (low < high) {
    int mid = (low + high + 1) >> 1;
    int ty = mid;
    int tx = int((ll)ty * a / b);
    int tz = int((ll)ty * c / b);
    if (test(x, y, z, tx, ty, tz))
      low = mid;
    else
      high = mid - 1;
  }
  int ty = low;
  int tx = int((ll)ty * a / b);
  int tz = int((ll)ty * c / b);
  bmax(xx, tx), bmax(yy, ty), bmax(zz, tz);
}

void jumpz(int x, int y, int z, int &xx, int &yy, int &zz) {
  int low = z, high = c - 1;
  while (low < high) {
    int mid = (low + high + 1) >> 1;
    int tz = mid;
    int ty = int((ll)tz * b / c);
    int tx = int((ll)tz * a / c);
    if (test(x, y, z, tx, ty, tz))
      low = mid;
    else
      high = mid - 1;
  }
  int tz = low;
  int ty = int((ll)tz * b / c);
  int tx = int((ll)tz * a / c);
  bmax(xx, tx), bmax(yy, ty), bmax(zz, tz);
}

void jumpnext(int x, int y, int z, int &xx, int &yy, int &zz) {
  xx = x, yy = y, zz = z;
  jumpx(x, y, z, xx, yy, zz);
  jumpy(x, y, z, xx, yy, zz);
  jumpz(x, y, z, xx, yy, zz);
}

int x[MAXN], y[MAXN], z[MAXN], v[MAXN], v2[MAXN], sz;
bool checkend() {
  return x[sz - 1] == a - 1 && y[sz - 1] == b - 1 && z[sz - 1] == c - 1;
}
void solve() {
  x[sz] = y[sz] = z[sz] = 0;
  v[sz++] = calc(-d, d, -d, d, -d, d);
  while (!checkend()) {
    int xx, yy, zz;
    nextblock(x[sz - 1], y[sz - 1], z[sz - 1], xx, yy, zz);
    v2[sz - 1] = calc2(xx, yy, zz, x[sz - 1], y[sz - 1], z[sz - 1]);
    jumpnext(x[sz - 1], y[sz - 1], z[sz - 1], x[sz], y[sz], z[sz]);
    xx = x[sz], yy = y[sz], zz = z[sz];
    // printf( "x = %d, y = %d, z = %d, (pre)\\n", xx, yy, zz );
    nextblock(xx, yy, zz, x[sz], y[sz], z[sz]);
    v[sz] = calc2(x[sz], y[sz], z[sz], xx, yy, zz);
    // printf( "x = %d, y = %d, z = %d, sz = %d\\n", x[sz], y[sz], z[sz], sz );
    ++sz;
  }
  int ans = 0;
  for (int i = 1; i < sz; ++i) {
    ll cnt = (ll)x[i] - x[i - 1] + y[i] - y[i - 1] + z[i] - z[i - 1];
    ans = int((ans + v[i - 1] + (cnt - 1) % MOD * v2[i - 1]) % MOD);
  }
  printf("%d\\n", (ans + (d == 0)) % MOD);
}

int main() {
  _w = scanf("%d%d%d%d", &a, &b, &c, &d);
  solve();
  return 0;
}


#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ext/pb_ds/priority_queue.hpp>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
using namespace std;

const int N = 303;
typedef long long LL;
const LL mo = 1000000007;

int n, k, x, Ans = 1, s[N], f[N][N], q[N];

inline int Mul(const LL &x, const LL &y) { return x * y % mo; }
inline int min(const int &x, const int &y) { return x < y ? x : y; }
inline int max(const int &x, const int &y) { return x > y ? x : y; }
inline int Add(const int &x, const int &y) {
  return x + y < mo ? x + y : x + y - mo;
}
inline int Dec(const int &x, const int &y) {
  return x - y >= 0 ? x - y : x - y + mo;
}

int ksm(int x, int y) {
  int ret = 1;
  for (; y; y >>= 1) {
    if (y & 1)
      ret = Mul(ret, x);
    x = Mul(x, x);
  }
  return ret;
}

inline int Solve(int tot, int L, int R, int sum) {
  f[1][1] = 1;
  for (int j = 2; j <= sum; j++) {
    int head, tail, cnt;
    cnt = f[j - 1][j - 1];
    q[head = tail = 1] = j - 1;
    for (int i = j, TT = tot - sum + j; i <= TT; i++) {
      while (head <= tail) {
        int l = q[head], r = i;
        int nl = max(L - j + 2, R - sum + j - 1);
        if (nl < 0) {
          cnt = Dec(cnt, f[q[head]][j - 1]);
          ++head;
          continue;
        }
        int nr = max(L - j + 1, R - sum + j);
        if (nr < 0) {
          cnt = Dec(cnt, f[q[head]][j - 1]);
          ++head;
          continue;
        }
        if (nl + nr < r - l - 1) {
          cnt = Dec(cnt, f[q[head]][j - 1]);
          ++head;
          continue;
        }
        break;
      }
      f[i][j] = cnt;
      if (f[i][j - 1])
        q[++tail] = i, cnt = Add(cnt, f[i][j - 1]);
    }
  }
  return f[tot][sum];
}

inline int Calc(int tot, int L, int R) {
  if (L < 0 || R < 0)
    return 0;
  if (L + R >= tot - 2)
    return ksm(2, tot - 2);
  int ret = 0;
  for (int i = 1; i <= tot - 2; i++)
    ret = Add(ret, Solve(tot, L, R, i + 2));
  return ret;
}

int main() {
#ifdef DMC
  freopen("DMC.txt", "r", stdin);
#endif

  cin >> n >> k >> x;
  for (int i = 0; i < k; i++)
    scanf("%d", &s[i]);
  for (int i = 1; i < k; i++) {
    if (s[i] - s[i - 1] == 1)
      continue;
    int L = max(x - i + 1, k - i);
    int R = max(x - i, k - 1 - i);
    Ans = Mul(Ans, Calc(s[i] - s[i - 1] + 1, L, R));
    if (!Ans) {
      cout << 0 << endl;
      return 0;
    }
  }
  cout << Ans << endl;
  return 0;
}

#include <algorithm>
#include <bitset>
#include <cmath>
#include <cstdio>
#include <cstring>
#include <ext/pb_ds/priority_queue.hpp>
#include <iostream>
#include <map>
#include <queue>
#include <set>
#include <stack>
#include <vector>
using namespace std;

const int maxn = 5005;
const int maxm = 1E4 + 10;
typedef long long LL;
const LL mo = 1000000007;

int n, k, x, tail, Ans = 1, s[maxn], f[maxn][maxm];

inline int Mul(const LL &x, const LL &y) { return x * y % mo; }
inline int Add(const int &x, const int &y) {
  return x + y < mo ? x + y : x + y - mo;
}
inline int Dec(const int &x, const int &y) {
  return x - y >= 0 ? x - y : x - y + mo;
}

int main() {
#ifdef DMC
  freopen("DMC.txt", "r", stdin);
#endif

  f[0][1] = 1;
  cin >> n >> k >> x;
  for (int i = 0; i < k; i++)
    scanf("%d", &s[i]);
  for (int i = 1; i < k; i++)
    tail = max(tail, s[i] - s[i - 1]);
  for (int i = 1; i <= 2 * x; i++) {
    int sum = 0, Max = i + (i & 1);
    for (int j = 1; j <= tail; j++) {
      sum = Add(sum, f[i - 1][j - 1]);
      if (j - Max - 1 >= 0)
        sum = Dec(sum, f[i - 1][j - Max - 1]);
      f[i][j] = sum;
      if (i + 1 >= j)
        f[i][j] = Add(f[i][j], 1);
    }
  }
  for (int i = 1; i < k; i++)
    Ans = Mul(Ans, f[2 * x - 2 * i + 1][s[i] - s[i - 1]]);
  cout << Ans << endl;
  return 0;
}


#include <algorithm>
#include <array>
#include <chrono>
#include <cmath>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <string>
#include <tuple>
#include <unordered_set>
#include <vector>
using namespace std;
typedef long long int llint;
typedef long double lldo;
#define mp make_pair
#define mt make_tuple
#define pub push_back
#define puf push_front
#define pob pop_back
#define pof pop_front
#define fir first
#define sec second
#define res resize
#define ins insert
#define era erase
// cout<<setprecision(20)
const llint mod = 1000000007;
const llint big = 2.19e15 + 1;
const long double pai = 3.141592653589793238462643383279502884197;
const long double eps = 1e-15;
template <class T, class U> void mineq(T &a, U b) {
  if (a > b) {
    a = b;
  }
}
template <class T, class U> void maxeq(T &a, U b) {
  if (a < b) {
    a = b;
  }
}
llint gcd(llint a, llint b) {
  if (a % b == 0) {
    return b;
  } else
    return gcd(b, a % b);
}
llint lcm(llint a, llint b) { return a / gcd(a, b) * b; }
template <class T> void SO(T &ve) { sort(ve.begin(), ve.end()); }
template <class T> void REV(T &ve) { reverse(ve.begin(), ve.end()); }
int LBI(vector<lldo> &ar, lldo in) {
  return lower_bound(ar.begin(), ar.end(), in) - ar.begin();
}
int UBI(vector<lldo> &ar, lldo in) {
  return upper_bound(ar.begin(), ar.end(), in) - ar.begin();
}
int main(void) {
  cin.tie(0);
  ios::sync_with_stdio(false);
  int n, K, X, i, j;
  cin >> n >> K >> X;
  static llint dp[2501][2501] = {0};
  static llint ep[2501][2501] = {0};
  // 左側の残り時間,駅間,の累積WA,dpなら右=左-1,epなら右=左
  // これを前計算
  for (j = 2; j <= n; j++) {
    ep[0][j] = 1;
  }
  for (i = 1; i <= X; i++) { // dp
    dp[i][1] = 1;
    ep[i][1] = 1;
    for (j = 2; j <= n + 1; j++) {
      dp[i][j] = (mod + dp[i][j - 1] + ep[i - 1][j - 1] -
                  ep[i - 1][max(0, j - i - i - 1)]) %
                 mod;
    } // 駅間
    for (j = 2; j <= n + 1; j++) {
      ep[i][j] =
          (mod + ep[i][j - 1] + dp[i][j - 1] - dp[i][max(0, j - i - i - 1)]) %
          mod;
    } // 駅間
    // for(j=1;j<=n+1;j++){cerr<<dp[i][j]<<" ";}
    // cerr<<endl;
    // for(j=1;j<=n+1;j++){cerr<<ep[i][j]<<" ";}
    // cerr<<endl;
  }
  llint ans = 1, mae;
  cin >> mae;
  for (i = 0; i < K - 1; i++) {
    int s;
    cin >> s;
    ans *= (mod + ep[X - i][1 + s - mae] - ep[X - i][s - mae]);
    ans %= mod;
    mae = s;
  }
  cout << ans << endl;
  return 0;
}

#include <algorithm>
#include <array>
#include <chrono>
#include <cmath>
#include <deque>
#include <functional>
#include <iomanip>
#include <iostream>
#include <iterator>
#include <map>
#include <queue>
#include <random>
#include <set>
#include <string>
#include <tuple>
#include <unordered_set>
#include <vector>
using namespace std;
typedef long long int llint;
typedef long double lldo;
#define mp make_pair
#define mt make_tuple
#define pub push_back
#define puf push_front
#define pob pop_back
#define pof pop_front
#define fir first
#define sec second
#define res resize
#define ins insert
#define era erase
// cout<<setprecision(20)
const llint mod = 1000000007;
const llint big = 2.19e15 + 1;
const long double pai = 3.141592653589793238462643383279502884197;
const long double eps = 1e-15;
template <class T, class U> void mineq(T &a, U b) {
  if (a > b) {
    a = b;
  }
}
template <class T, class U> void maxeq(T &a, U b) {
  if (a < b) {
    a = b;
  }
}
llint gcd(llint a, llint b) {
  if (a % b == 0) {
    return b;
  } else
    return gcd(b, a % b);
}
llint lcm(llint a, llint b) { return a / gcd(a, b) * b; }
template <class T> void SO(T &ve) { sort(ve.begin(), ve.end()); }
template <class T> void REV(T &ve) { reverse(ve.begin(), ve.end()); }
int LBI(vector<lldo> &ar, lldo in) {
  return lower_bound(ar.begin(), ar.end(), in) - ar.begin();
}
int UBI(vector<lldo> &ar, lldo in) {
  return upper_bound(ar.begin(), ar.end(), in) - ar.begin();
}
int main(void) {
  cin.tie(0);
  ios::sync_with_stdio(false);
  int n, K, X, i, j;
  cin >> n >> K >> X;
  mineq(n, 10000);
  // static llint cp[2505][10005]={0};
  static llint dp[2505][10005] = {0};
  static llint ep[2505][10005] = {0};
  // 左側の残り時間,駅間,の累積WA,dpなら右=左-1,epなら右=左 cpなら片方のみ
  // これを前計算
  ep[0][1] = 1;
  for (j = 2; j <= n; j++) {
    ep[0][j] = 2;
  }
  for (i = 1; i <= X; i++) { // dp
    dp[i][1] = 1;
    ep[i][1] = 1;
    for (j = 1; j <= n; j++) {
      dp[i][j + 1] =
          (mod + dp[i][j] + ep[i - 1][j] - ep[i - 1][max(0, j - i - i)]) % mod;
    } // 駅間
    for (j = 1; j <= n; j++) {
      ep[i][j + 1] =
          (mod + ep[i][j] + dp[i][j] - dp[i][max(0, j - i - i)]) % mod;
      if (j == i + i + 1) {
        ep[i][j + 1]++;
      }
    } // 駅間
    /*for(j=1;j<=n+1;j++){cerr<<dp[i][j]<<" ";}
    cerr<<endl;
    for(j=1;j<=n+1;j++){cerr<<ep[i][j]<<" ";}
    cerr<<endl;*/
  }
  llint ans = 1, mae;
  cin >> mae;
  for (i = 0; i < K - 1; i++) {
    int s;
    cin >> s;
    ans *= (mod + dp[X - i][1 + s - mae] - dp[X - i][s - mae]);
    ans %= mod;
    mae = s;
  }
  cout << ans << endl;
  return 0;
}

/tmp/af6dc7a1-01af-46aa-aa23-41547c9455b1.out: error while loading shared libraries: libc.so.6: failed to map segment from shared object


#include <bits/stdc++.h>
#define ll long long
#define inf 1000000000000000000ll
#define N 420005
#define M 2000005
using namespace std;

const int dx[4] = {-1, 1, 0, 0}, dy[4] = {0, 0, -1, 1};
int H, W, n, cnt, C, tot, fst[N], pnt[M], len[M], nxt[M];
int hsh[2010527], nxt_h[M], mn[M], pos[N];
ll d[N];
bool bo[N];
struct node {
  int x, y, z, id;
} p[N];
int getdct(char c) {
  if (c == 'N')
    return 0;
  else if (c == 'S')
    return 1;
  else if (c == 'W')
    return 2;
  else
    return 3;
}
int calc(int x, int y, int z) {
  // if (x<=0 || x>H || y<=0 || y>W) return 0;
  int t = (x * 100000ll + y) % 2010527, i;
  for (i = hsh[t]; i; i = nxt_h[i])
    if (p[i].x == x && p[i].y == y && p[i].z == z)
      return i;
  // cout<<x<<' '<<y<<' '<<z<<' '<<cnt+1<<endl;
  cnt++;
  p[cnt] = (node){x, y, z, cnt};
  nxt_h[cnt] = hsh[t];
  hsh[t] = cnt;
  return cnt;
}
void add(int x, int y, ll z) {
  if (!x || !y)
    return;
  //	cout<<"				"<<x<<' '<<y<<' '<<z<<endl;
  pnt[++tot] = y;
  len[tot] = z;
  nxt[tot] = fst[x];
  fst[x] = tot;
}
void build(int k, int l, int r) {
  mn[k] = l;
  if (l == r) {
    pos[l] = k;
    return;
  }
  int mid = l + r >> 1;
  build(k << 1, l, mid);
  build(k << 1 | 1, mid + 1, r);
}
void mdy(int x) {
  int i;
  for (i = pos[x] >> 1; i; i >>= 1)
    mn[i] = (d[mn[i << 1]] < d[mn[i << 1 | 1]]) ? mn[i << 1] : mn[i << 1 | 1];
}
bool cmpx(node u, node v) {
  return u.x < v.x || u.x == v.x && u.y < v.y ||
         u.x == v.x && u.y == v.y && u.z < v.z;
}
bool cmpy(node u, node v) {
  return u.y < v.y || u.y == v.y && u.x < v.x ||
         u.x == v.x && u.y == v.y && u.z < v.z;
}
int main() {
  scanf("%d%d%d%d", &H, &W, &n, &C);
  int x1, x2, y1, y2, i, j, k, l, x, y, cst;
  char c;
  scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
  calc(x1, y1, 0);
  calc(x2, y2, 0);
  for (i = 1; i <= 2; i++)
    add(calc(x2, y2, i), calc(x2, y2, 0), 0);
  for (i = 1; i <= n; i++) {
    scanf("%d%d %c%d%d", &x, &y, &c, &l, &cst);
    //	cout<<"("<<c<<")"<<endl;
    k = getdct(c);
    //	cout<<k<<endl;
    //	cout<<x<<' '<<y<<' '<<c<<' '<<l<<' '<<cst<<endl;
    for (j = 1; j <= 2; j++)
      add(calc(x, y, j), calc(x, y, 0), 0);
    for (j = 0; j < 4; j++)
      add(calc(x, y, 0), calc(x + dx[j] * l, y + dy[j] * l, (j > 1) ? 1 : 2),
          (j == k) ? 0 : cst);
  }
  // cout<<cnt<<endl;
  sort(p + 1, p + cnt + 1, cmpx);
  for (i = 1; i <= cnt; i = j)
    for (j = i, k = 0; p[i].x == p[j].x; j++) {
      //	cout<<p[j].x<<' '<<p[j].y<<' '<<p[j].z<<endl;
      if (p[j].z == 1) {
        add(p[j].id, p[k].id, (ll)(p[j].y - p[k].y) * C);
        add(p[k].id, p[j].id, (ll)(p[j].y - p[k].y) * C);
        k = j;
      }
    }
  sort(p + 1, p + cnt + 1, cmpy);
  for (i = 1; i <= cnt; i = j)
    for (j = i, k = 0; p[i].y == p[j].y; j++)
      if (p[j].z == 2) {
        add(p[j].id, p[k].id, (ll)(p[j].x - p[k].x) * C);
        add(p[k].id, p[j].id, (ll)(p[j].x - p[k].x) * C);
        k = j;
      }
  for (i = 2; i <= cnt; i++)
    d[i] = inf;
  memset(bo, 1, sizeof(bo));
  build(1, 1, cnt);
  for (i = 1; i <= cnt; i++) {
    x = mn[1];
    if (x == 2)
      break;
    bo[x] = 0;
    for (j = fst[x]; j; j = nxt[j]) {
      y = pnt[j];
      if (bo[y] && d[x] + len[j] < d[y]) {
        //	cout<<x<<"->"<<y<<endl;
        d[y] = d[x] + len[j];
        mdy(y);
      }
    }
    d[x] = inf;
    mdy(x);
  }
  printf("%lld\\n", (d[2] < inf) ? d[2] : -1);
  return 0;
}

#include <bits/stdc++.h>
#define ll long long
#define inf 1000000000000000000ll
#define N 1000005
#define M 4000005
using namespace std;

const int dx[4] = {-1, 1, 0, 0}, dy[4] = {0, 0, -1, 1};
int H, W, n, cnt, C, tot, fst[N], pnt[M], nxt[M];
int hsh[2010527], nxt_h[M], mn[M], pos[N];
ll d[N], len[M];
bool bo[N];
struct node {
  int x, y, z, id;
} p[N];
int getdct(char c) {
  if (c == 'N')
    return 0;
  else if (c == 'S')
    return 1;
  else if (c == 'W')
    return 2;
  else
    return 3;
}
int calc(int x, int y, int z) {
  // if (x<=0 || x>H || y<=0 || y>W) return 0;
  int t = (x * 100000ll + y) % 2010527, i;
  for (i = hsh[t]; i; i = nxt_h[i])
    if (p[i].x == x && p[i].y == y && p[i].z == z)
      return i;
  // cout<<x<<' '<<y<<' '<<z<<' '<<cnt+1<<endl;
  cnt++;
  p[cnt] = (node){x, y, z, cnt};
  nxt_h[cnt] = hsh[t];
  hsh[t] = cnt;
  return cnt;
}
void add(int x, int y, ll z) {
  if (!x || !y)
    return;
  //	cout<<"				"<<x<<' '<<y<<' '<<z<<endl;
  pnt[++tot] = y;
  len[tot] = z;
  nxt[tot] = fst[x];
  fst[x] = tot;
}
void build(int k, int l, int r) {
  mn[k] = l;
  if (l == r) {
    pos[l] = k;
    return;
  }
  int mid = l + r >> 1;
  build(k << 1, l, mid);
  build(k << 1 | 1, mid + 1, r);
}
void mdy(int x) {
  int i;
  for (i = pos[x] >> 1; i; i >>= 1)
    mn[i] = (d[mn[i << 1]] < d[mn[i << 1 | 1]]) ? mn[i << 1] : mn[i << 1 | 1];
}
bool cmpx(node u, node v) {
  return u.x < v.x || u.x == v.x && u.y < v.y ||
         u.x == v.x && u.y == v.y && u.z < v.z;
}
bool cmpy(node u, node v) {
  return u.y < v.y || u.y == v.y && u.x < v.x ||
         u.x == v.x && u.y == v.y && u.z < v.z;
}
int main() {
  scanf("%d%d%d%d", &H, &W, &n, &C);
  int x1, x2, y1, y2, i, j, k, l, x, y, cst;
  char c;
  scanf("%d%d%d%d", &x1, &y1, &x2, &y2);
  calc(x1, y1, 0);
  calc(x2, y2, 0);
  for (i = 1; i <= 2; i++)
    add(calc(x2, y2, i), calc(x2, y2, 0), 0);
  for (i = 1; i <= n; i++) {
    scanf("%d%d %c%d%d", &x, &y, &c, &l, &cst);
    //	cout<<"("<<c<<")"<<endl;
    k = getdct(c);
    //	cout<<k<<endl;
    //	cout<<x<<' '<<y<<' '<<c<<' '<<l<<' '<<cst<<endl;
    for (j = 1; j <= 2; j++)
      add(calc(x, y, j), calc(x, y, 0), 0);
    for (j = 0; j < 4; j++)
      add(calc(x, y, 0), calc(x + dx[j] * l, y + dy[j] * l, (j > 1) ? 1 : 2),
          (j == k) ? 0 : cst);
  }
  // cout<<cnt<<endl;
  sort(p + 1, p + cnt + 1, cmpx);
  for (i = 1; i <= cnt; i = j)
    for (j = i, k = 0; p[i].x == p[j].x; j++) {
      //	cout<<p[j].x<<' '<<p[j].y<<' '<<p[j].z<<endl;
      if (p[j].z == 1) {
        add(p[j].id, p[k].id, (ll)(p[j].y - p[k].y) * C);
        add(p[k].id, p[j].id, (ll)(p[j].y - p[k].y) * C);
        k = j;
      }
    }
  sort(p + 1, p + cnt + 1, cmpy);
  for (i = 1; i <= cnt; i = j)
    for (j = i, k = 0; p[i].y == p[j].y; j++)
      if (p[j].z == 2) {
        add(p[j].id, p[k].id, (ll)(p[j].x - p[k].x) * C);
        add(p[k].id, p[j].id, (ll)(p[j].x - p[k].x) * C);
        k = j;
      }
  for (i = 2; i <= cnt; i++)
    d[i] = inf;
  memset(bo, 1, sizeof(bo));
  build(1, 1, cnt);
  for (i = 1; i <= cnt; i++) {
    x = mn[1];
    if (x == 2)
      break;
    bo[x] = 0;
    for (j = fst[x]; j; j = nxt[j]) {
      y = pnt[j];
      if (bo[y] && d[x] + len[j] < d[y]) {
        //	cout<<x<<"->"<<y<<endl;
        d[y] = d[x] + len[j];
        mdy(y);
      }
    }
    d[x] = inf;
    mdy(x);
  }
  printf("%lld\\n", (d[2] < inf) ? d[2] : -1);
  return 0;
}


#include <algorithm>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

#define PB push_back
#define MP make_pair
#define SZ(v) ((int)(v).size())
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORE(i, a, b) for (int i = (a); i <= (b); ++i)
#define REPE(i, n) FORE(i, 0, n)
#define FORSZ(i, a, v) FOR(i, a, SZ(v))
#define REPSZ(i, v) REP(i, SZ(v))
typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }

const int MAXN = 70000 + 1;
const int DX[] = {-1, 0, +1, 0}, DY[] = {0, +1, 0, -1};
char DC[] = {'N', 'E', 'S', 'W'};
typedef struct P {
  int u, v, idx, t;
} P;
bool operator<(const P &a, const P &b) {
  if (a.t != b.t)
    return a.t < b.t;
  if (a.u != b.u)
    return a.u < b.u;
  if (a.v != b.v)
    return a.v < b.v;
  return a.idx < b.idx;
}

int h, w, n, dcost;
int sx, sy, tx, ty;

int ax[MAXN], ay[MAXN], ak[MAXN], ad[MAXN], akcost[MAXN];
ll d[MAXN];

P p[2 * MAXN];
ll mninc[8 * MAXN], mndec[8 * MAXN], mn[8 * MAXN];
int fst[8 * MAXN], lst[8 * MAXN], mnpos[8 * MAXN];

void updinc(int x, ll val) {
  if (val >= mninc[x])
    return;
  mninc[x] = val;
  if (fst[x] != -1) {
    ll cur = mninc[x] + (ll)dcost * p[fst[x]].v;
    if (cur < mn[x])
      mn[x] = cur, mnpos[x] = fst[x];
  }
}
void upddec(int x, ll val) {
  if (val >= mndec[x])
    return;
  mndec[x] = val;
  if (lst[x] != -1) {
    ll cur = mndec[x] - (ll)dcost * p[lst[x]].v;
    if (cur < mn[x])
      mn[x] = cur, mnpos[x] = lst[x];
  }
}
void spush(int x) {
  if (mninc[x] != LLONG_MAX)
    updinc(2 * x + 1, mninc[x]), updinc(2 * x + 2, mninc[x]),
        mninc[x] = LLONG_MAX;
  if (mndec[x] != LLONG_MAX)
    upddec(2 * x + 1, mndec[x]), upddec(2 * x + 2, mndec[x]),
        mndec[x] = LLONG_MAX;
}
void scalc(int x) {
  fst[x] = fst[2 * x + 1] != -1 ? fst[2 * x + 1] : fst[2 * x + 2];
  lst[x] = lst[2 * x + 1] != -1 ? lst[2 * x + 2] : lst[2 * x + 1];
  mn[x] = LLONG_MAX, mnpos[x] = -1;
  if (mninc[x] != LLONG_MAX && fst[x] != -1) {
    ll cur = mninc[x] + (ll)dcost * p[fst[x]].v;
    if (cur < mn[x])
      mn[x] = cur, mnpos[x] = fst[x];
  }
  if (mndec[x] != LLONG_MAX && lst[x] != -1) {
    ll cur = mndec[x] - (ll)dcost * p[lst[x]].v;
    if (cur < mn[x])
      mn[x] = cur, mnpos[x] = lst[x];
  }
  if (mn[2 * x + 1] < mn[x])
    mn[x] = mn[2 * x + 1], mnpos[x] = mnpos[2 * x + 1];
  if (mn[2 * x + 2] < mn[x])
    mn[x] = mn[2 * x + 2], mnpos[x] = mnpos[2 * x + 2];
}
void sinit(int x, int l, int r) {
  mninc[x] = mndec[x] = LLONG_MAX;
  if (l == r) {
    mn[x] = LLONG_MAX;
    fst[x] = lst[x] = mnpos[x] = l;
    return;
  }
  int m = l + (r - l) / 2;
  sinit(2 * x + 1, l, m);
  sinit(2 * x + 2, m + 1, r);
  scalc(x);
}
void sset(int x, int l, int r, int POS, ll VAL) {
  if (l == r) {
    mn[x] = VAL;
    return;
  }
  int m = l + (r - l) / 2;
  spush(x);
  if (POS <= m)
    sset(2 * x + 1, l, m, POS, VAL);
  else
    sset(2 * x + 2, m + 1, r, POS, VAL);
  scalc(x);
}
void skill(int x, int l, int r, int POS) {
  if (l == r) {
    fst[x] = lst[x] = mnpos[x] = -1;
    mn[x] = LLONG_MAX;
    return;
  }
  int m = l + (r - l) / 2;
  spush(x);
  if (POS <= m)
    skill(2 * x + 1, l, m, POS);
  else
    skill(2 * x + 2, m + 1, r, POS);
  scalc(x);
}
void sinc(int x, int l, int r, int T, int U, int V, ll VAL) {
  if (T < p[l].t || T == p[l].t && (U < p[l].u))
    return;
  if (T > p[r].t || T == p[r].t && (U > p[r].u || U == p[r].u && (V > p[r].v)))
    return;
  // printf("sinc(%d,%d..%d,[%d,%d,%d],%lld) [%d,%d,%d]
  // [%d,%d,%d]\\n",x,l,r,T,U,V,VAL,p[l].t,p[l].u,p[l].v,p[r].t,p[r].u,p[r].v);
  if (T == p[l].t && T == p[r].t && U == p[l].u && U == p[r].u && V <= p[l].v) {
    updinc(x, VAL);
  } else {
    int m = l + (r - l) / 2;
    spush(x);
    sinc(2 * x + 1, l, m, T, U, V, VAL);
    sinc(2 * x + 2, m + 1, r, T, U, V, VAL);
    scalc(x);
  }
}
void sdec(int x, int l, int r, int T, int U, int V, ll VAL) {
  if (T < p[l].t || T == p[l].t && (U < p[l].u || U == p[l].u && (V < p[l].v)))
    return;
  if (T > p[r].t || T == p[r].t && (U > p[r].u))
    return;
  if (T == p[l].t && T == p[r].t && U == p[l].u && U == p[r].u && V >= p[r].v) {
    upddec(x, VAL);
  } else {
    int m = l + (r - l) / 2;
    spush(x);
    sdec(2 * x + 1, l, m, T, U, V, VAL);
    sdec(2 * x + 2, m + 1, r, T, U, V, VAL);
    scalc(x);
  }
}

void run() {
  scanf("%d%d%d%d", &h, &w, &n, &dcost);
  scanf("%d%d%d%d", &sx, &sy, &tx, &ty);
  --sx, --sy, --tx, --ty;
  REP(i, n) {
    char c;
    scanf("%d%d %c%d%d", &ax[i], &ay[i], &c, &ad[i], &akcost[i]);
    --ax[i], --ay[i], ak[i] = -1;
    REP(k, 4) if (DC[k] == c) ak[i] = k;
    assert(ak[i] != -1);
  }
  ax[n] = tx, ay[n] = ty, ak[n] = -1, ad[n] = 0, akcost[n] = 0, ++n;

  REP(i, n) p[i].u = ax[i], p[i].v = ay[i], p[i].idx = i, p[i].t = 0;
  REP(i, n)
  p[n + i].u = ay[i],
        p[n + i].v = ax[i], p[n + i].idx = i, p[n + i].t = 1;
  sort(p, p + 2 * n);
  sinit(0, 0, 2 * n - 1);
  REP(i, n) d[i] = LLONG_MAX;
  REP(i, 2 * n)
  if (p[i].t == 0 && p[i].u == sx && p[i].v == sy ||
      p[i].t == 1 && p[i].u == sy && p[i].v == sx) sset(0, 0, 2 * n - 1, i, 0);
  while (mn[0] != LLONG_MAX) {
    int pos = mnpos[0], idx = p[pos].idx;
    ll cost = mn[0];
    // printf("pos=%d (u=%d,v=%d,idx=%d,t=%d) =
    // %lld\\n",pos,p[pos].u,p[pos].v,p[pos].idx,p[pos].t,cost);
    skill(0, 0, 2 * n - 1, pos);
    if (d[idx] == LLONG_MAX)
      d[idx] = cost;
    else {
      assert(cost >= d[idx]);
      continue;
    }
    if (ak[idx] == -1)
      continue;
    REP(k, 4) {
      ll ncost = cost + (k == ak[idx] ? 0 : akcost[idx]);
      int x = ax[idx] + ad[idx] * DX[k], y = ay[idx] + ad[idx] * DY[k],
          t = DX[k] == 0 ? 0 : 1, u = t == 0 ? x : y, v = t == 0 ? y : x;
      // printf("\\t->(%d,%d)=%lld (%d,%d)\\n",x,y,ncost,DX[k],DY[k]);
      sdec(0, 0, 2 * n - 1, t, u, v, ncost + (ll)dcost * v);
      sinc(0, 0, 2 * n - 1, t, u, v, ncost - (ll)dcost * v);
    }
  }
  ll ret = d[n - 1];
  printf("%lld\\n", ret == LLONG_MAX ? -1 : ret);
}

int main() {
  run();
  return 0;
}

#include <algorithm>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

#define PB push_back
#define MP make_pair
#define SZ(v) ((int)(v).size())
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORE(i, a, b) for (int i = (a); i <= (b); ++i)
#define REPE(i, n) FORE(i, 0, n)
#define FORSZ(i, a, v) FOR(i, a, SZ(v))
#define REPSZ(i, v) REP(i, SZ(v))
typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }

const int MAXN = 70000 + 1;
const int DX[] = {-1, 0, +1, 0}, DY[] = {0, +1, 0, -1};
char DC[] = {'N', 'E', 'S', 'W'};
typedef struct P {
  int u, v, idx, t;
} P;
bool operator<(const P &a, const P &b) {
  if (a.t != b.t)
    return a.t < b.t;
  if (a.u != b.u)
    return a.u < b.u;
  if (a.v != b.v)
    return a.v < b.v;
  return a.idx < b.idx;
}

int h, w, n, dcost;
int sx, sy, tx, ty;

int ax[MAXN], ay[MAXN], ak[MAXN], ad[MAXN], akcost[MAXN];
ll d[MAXN];

P p[2 * MAXN];
ll mninc[8 * MAXN], mndec[8 * MAXN], mn[8 * MAXN];
int fst[8 * MAXN], lst[8 * MAXN], mnpos[8 * MAXN];

void updinc(int x, ll val) {
  if (val >= mninc[x])
    return;
  mninc[x] = val;
  if (fst[x] != -1) {
    ll cur = mninc[x] + (ll)dcost * p[fst[x]].v;
    if (cur < mn[x])
      mn[x] = cur, mnpos[x] = fst[x];
  }
}
void upddec(int x, ll val) {
  if (val >= mndec[x])
    return;
  mndec[x] = val;
  if (lst[x] != -1) {
    ll cur = mndec[x] - (ll)dcost * p[lst[x]].v;
    if (cur < mn[x])
      mn[x] = cur, mnpos[x] = lst[x];
  }
}
void spush(int x) {
  if (mninc[x] != LLONG_MAX)
    updinc(2 * x + 1, mninc[x]), updinc(2 * x + 2, mninc[x]),
        mninc[x] = LLONG_MAX;
  if (mndec[x] != LLONG_MAX)
    upddec(2 * x + 1, mndec[x]), upddec(2 * x + 2, mndec[x]),
        mndec[x] = LLONG_MAX;
}
void scalc(int x) {
  fst[x] = fst[2 * x + 1] != -1 ? fst[2 * x + 1] : fst[2 * x + 2];
  lst[x] = lst[2 * x + 2] != -1 ? lst[2 * x + 2] : lst[2 * x + 1];
  mn[x] = LLONG_MAX, mnpos[x] = -1;
  if (mninc[x] != LLONG_MAX && fst[x] != -1) {
    ll cur = mninc[x] + (ll)dcost * p[fst[x]].v;
    if (cur < mn[x])
      mn[x] = cur, mnpos[x] = fst[x];
  }
  if (mndec[x] != LLONG_MAX && lst[x] != -1) {
    ll cur = mndec[x] - (ll)dcost * p[lst[x]].v;
    if (cur < mn[x])
      mn[x] = cur, mnpos[x] = lst[x];
  }
  if (mn[2 * x + 1] < mn[x])
    mn[x] = mn[2 * x + 1], mnpos[x] = mnpos[2 * x + 1];
  if (mn[2 * x + 2] < mn[x])
    mn[x] = mn[2 * x + 2], mnpos[x] = mnpos[2 * x + 2];
}
void sinit(int x, int l, int r) {
  mninc[x] = mndec[x] = LLONG_MAX;
  if (l == r) {
    mn[x] = LLONG_MAX;
    fst[x] = lst[x] = mnpos[x] = l;
    return;
  }
  int m = l + (r - l) / 2;
  sinit(2 * x + 1, l, m);
  sinit(2 * x + 2, m + 1, r);
  scalc(x);
}
void sset(int x, int l, int r, int POS, ll VAL) {
  if (l == r) {
    mn[x] = VAL;
    return;
  }
  int m = l + (r - l) / 2;
  spush(x);
  if (POS <= m)
    sset(2 * x + 1, l, m, POS, VAL);
  else
    sset(2 * x + 2, m + 1, r, POS, VAL);
  scalc(x);
}
void skill(int x, int l, int r, int POS) {
  if (l == r) {
    fst[x] = lst[x] = mnpos[x] = -1;
    mn[x] = LLONG_MAX;
    return;
  }
  int m = l + (r - l) / 2;
  spush(x);
  if (POS <= m)
    skill(2 * x + 1, l, m, POS);
  else
    skill(2 * x + 2, m + 1, r, POS);
  scalc(x);
}
void sinc(int x, int l, int r, int T, int U, int V, ll VAL) {
  if (T < p[l].t || T == p[l].t && (U < p[l].u))
    return;
  if (T > p[r].t || T == p[r].t && (U > p[r].u || U == p[r].u && (V > p[r].v)))
    return;
  // printf("sinc(%d,%d..%d,[%d,%d,%d],%lld) [%d,%d,%d]
  // [%d,%d,%d]\\n",x,l,r,T,U,V,VAL,p[l].t,p[l].u,p[l].v,p[r].t,p[r].u,p[r].v);
  if (T == p[l].t && T == p[r].t && U == p[l].u && U == p[r].u && V <= p[l].v) {
    updinc(x, VAL);
  } else {
    int m = l + (r - l) / 2;
    spush(x);
    sinc(2 * x + 1, l, m, T, U, V, VAL);
    sinc(2 * x + 2, m + 1, r, T, U, V, VAL);
    scalc(x);
  }
}
void sdec(int x, int l, int r, int T, int U, int V, ll VAL) {
  if (T < p[l].t || T == p[l].t && (U < p[l].u || U == p[l].u && (V < p[l].v)))
    return;
  if (T > p[r].t || T == p[r].t && (U > p[r].u))
    return;
  if (T == p[l].t && T == p[r].t && U == p[l].u && U == p[r].u && V >= p[r].v) {
    upddec(x, VAL);
  } else {
    int m = l + (r - l) / 2;
    spush(x);
    sdec(2 * x + 1, l, m, T, U, V, VAL);
    sdec(2 * x + 2, m + 1, r, T, U, V, VAL);
    scalc(x);
  }
}

ll solve() {
  ax[n] = tx, ay[n] = ty, ak[n] = -1, ad[n] = 0, akcost[n] = 0, ++n;

  REP(i, n) p[i].u = ax[i], p[i].v = ay[i], p[i].idx = i, p[i].t = 0;
  REP(i, n)
  p[n + i].u = ay[i],
        p[n + i].v = ax[i], p[n + i].idx = i, p[n + i].t = 1;
  sort(p, p + 2 * n);
  sinit(0, 0, 2 * n - 1);
  REP(i, n) d[i] = LLONG_MAX;
  REP(i, 2 * n)
  if (p[i].t == 0 && p[i].u == sx && p[i].v == sy ||
      p[i].t == 1 && p[i].u == sy && p[i].v == sx) sset(0, 0, 2 * n - 1, i, 0);
  while (mn[0] != LLONG_MAX) {
    int pos = mnpos[0], idx = p[pos].idx;
    ll cost = mn[0];
    // printf("pos=%d (u=%d,v=%d,idx=%d,t=%d) =
    // %lld\\n",pos,p[pos].u,p[pos].v,p[pos].idx,p[pos].t,cost);
    skill(0, 0, 2 * n - 1, pos);
    if (d[idx] == LLONG_MAX)
      d[idx] = cost;
    else {
      assert(cost >= d[idx]);
      continue;
    }
    if (ak[idx] == -1)
      continue;
    REP(k, 4) {
      ll ncost = cost + (k == ak[idx] ? 0 : akcost[idx]);
      int x = ax[idx] + ad[idx] * DX[k], y = ay[idx] + ad[idx] * DY[k],
          t = DX[k] == 0 ? 0 : 1, u = t == 0 ? x : y, v = t == 0 ? y : x;
      // printf("\\t->(%d,%d)=%lld (%d,%d)\\n",x,y,ncost,DX[k],DY[k]);
      sdec(0, 0, 2 * n - 1, t, u, v, ncost + (ll)dcost * v);
      sinc(0, 0, 2 * n - 1, t, u, v, ncost - (ll)dcost * v);
    }
  }
  ll ret = d[n - 1];
  return ret == LLONG_MAX ? -1 : ret;
}

void run() {
  scanf("%d%d%d%d", &h, &w, &n, &dcost);
  scanf("%d%d%d%d", &sx, &sy, &tx, &ty);
  --sx, --sy, --tx, --ty;
  REP(i, n) {
    char c;
    scanf("%d%d %c%d%d", &ax[i], &ay[i], &c, &ad[i], &akcost[i]);
    --ax[i], --ay[i], ak[i] = -1;
    REP(k, 4) if (DC[k] == c) ak[i] = k;
    assert(ak[i] != -1);
  }
  ll ret = solve();
  printf("%lld\\n", ret);
}

void stress() {
  while (true) {
    n = MAXN - 1;
    REP(i, n)
    ax[i] = rand() % 1000,
    ay[i] = rand() % 1000, ak[i] = rand() % 4, ad[i] = rand() % 1000,
    akcost[i] = rand() % 1000;
    dcost = rand() % 1000;
    {
      int s = rand() % n;
      sx = ax[s], sy = ay[s];
    }
    tx = rand() % 1000, ty = rand() % 1000;
    // printf("? ? %d %d\\n",n,dcost); printf("%d %d %d
    // %d\\n",sx+1,sy+1,tx+1,ty+1); REP(i,n) printf("%d %d %c %d
    // %d\\n",ax[i]+1,ay[i]+1,DC[ak[i]],ad[i],akcost[i]);
    solve();
    puts(".");
  }
}

int main() {
  // stress();
  run();
  return 0;
}


#include <algorithm>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

#define PB push_back
#define MP make_pair
#define SZ(v) ((int)(v).size())
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORE(i, a, b) for (int i = (a); i <= (b); ++i)
#define REPE(i, n) FORE(i, 0, n)
#define FORSZ(i, a, v) FOR(i, a, SZ(v))
#define REPSZ(i, v) REP(i, SZ(v))
typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }

const int MAXN = 400000;
const int MAXQ = 50000;
const int MAXEMP = MAXN + MAXQ;
const int SZ = 400;
const int MAXB = (MAXEMP + SZ - 1) / SZ;

int n, nq, nemp;
int par[MAXEMP], oval[MAXEMP];
bool alive[MAXEMP];
int qt[MAXQ], qemp[MAXQ], qd[MAXQ], qby[MAXQ];

int chead[MAXEMP], cnxt[MAXEMP];
int d[MAXEMP], lid[MAXEMP], rid[MAXEMP], emp[MAXEMP], nid;
void dfs(int at) {
  d[at] = par[at] == -1 ? 0 : d[par[at]] + 1;
  emp[nid] = at, lid[at] = nid++;
  for (int to = chead[at]; to != -1; to = cnxt[to])
    dfs(to);
  rid[at] = nid - 1;
}

int pos[MAXEMP];
int sd[MAXEMP];

typedef struct S {
  ll sval[4 * SZ];
  int slazy[4 * SZ];
  int scnt[4 * SZ];
  void clear() {
    memset(sval, 0, sizeof(sval));
    memset(slazy, 0, sizeof(slazy));
    memset(scnt, 0, sizeof(scnt));
  }
  void spush(int x) {
    if (slazy[x] == 0)
      return;
    sval[2 * x + 1] += slazy[x] * scnt[2 * x + 1];
    slazy[2 * x + 1] += slazy[x];
    sval[2 * x + 2] += slazy[x] * scnt[2 * x + 2];
    slazy[2 * x + 2] += slazy[x];
    slazy[x] = 0;
  }
  void scalc(int x) {
    scnt[x] = scnt[2 * x + 1] + scnt[2 * x + 2];
    sval[x] = sval[2 * x + 1] + sval[2 * x + 2];
  }
  void sborn(int x, int l, int r, int IDX, int VAL) {
    if (l == r) {
      sval[x] = VAL, slazy[x] = 0, scnt[x] = 1;
    } else {
      spush(x);
      int m = l + (r - l) / 2;
      if (IDX <= m)
        sborn(2 * x + 1, l, m, IDX, VAL);
      else
        sborn(2 * x + 2, m + 1, r, IDX, VAL);
      scalc(x);
    }
    // printf("sborn(%d,%d,%d,%d,%d) -> %d
    // %lld\\n",x,l,r,IDX,VAL,scnt[x],sval[x]);
  }
  void smod(int x, int l, int r, int L, int R, int BY) {
    if (L <= l && r <= R) {
      sval[x] += (ll)scnt[x] * BY;
      slazy[x] += BY;
    } else {
      spush(x);
      int m = l + (r - l) / 2;
      if (L <= m)
        smod(2 * x + 1, l, m, L, R, BY);
      if (m + 1 <= R)
        smod(2 * x + 2, m + 1, r, L, R, BY);
      scalc(x);
    }
    // printf("smod(%d,%d,%d,%d,%d,%d) -> %d %lld
    // %d\\n",x,l,r,L,R,BY,scnt[x],sval[x],slazy[x]);
  }
  ll sget(int x, int l, int r, int L, int R) {
    if (L <= l && r <= R) {
      return sval[x];
    } else {
      spush(x);
      int m = l + (r - l) / 2;
      ll ret = 0;
      if (L <= m)
        ret += sget(2 * x + 1, l, m, L, R);
      if (m + 1 <= R)
        ret += sget(2 * x + 2, m + 1, r, L, R);
      return ret;
    }
  }
  void save(int x, int l, int r, ll *val, int *cnt) {
    if (l == r) {
      val[l] = sval[x];
      cnt[l] = scnt[x];
    } else {
      spush(x);
      int m = l + (r - l) / 2;
      save(2 * x + 1, l, m, val, cnt);
      save(2 * x + 2, m + 1, r, val, cnt);
    }
  }
  void load(int x, int l, int r, ll *val, int *cnt) {
    if (l == r) {
      sval[x] = val[l], scnt[x] = cnt[x];
    } else {
      int m = l + (r - l) / 2;
      load(2 * x + 1, l, m, val, cnt);
      load(2 * x + 2, m + 1, r, val, cnt);
      scalc(x);
    }
  }
} S;
S s[MAXB];

int nb;
pair<int, int> tmp[SZ];
void build() {
  for (int i = 0; i < nemp; i += SZ) {
    int cnt = min(SZ, nemp - i);
    REP(j, cnt) tmp[j] = MP(d[emp[i + j]], emp[i + j]);
    sort(tmp, tmp + cnt);
    REP(j, cnt) sd[i + j] = tmp[j].first, pos[tmp[j].second] = i + j;
  }
  nb = (nemp + SZ - 1) / SZ;
  REP(i, nb) s[i].clear();
  REP(i, nemp)
  if (alive[i]) s[pos[i] / SZ].sborn(0, 0, SZ - 1, pos[i] % SZ, oval[i]);
  // REP(i,nemp) printf("%d: emp=%d d=%d pos=%d
  // oval=%d\\n",i,emp[i],d[emp[i]],pos[emp[i]],oval[emp[i]]); REP(i,nemp)
  // printf(" %d",sd[i]); puts("");
}

ll tval[SZ];
int tcnt[SZ];
ll query1(int idx, int ld, int rd) {
  // printf("query1(%d,%d,%d)\\n",idx,ld,rd);
  if (!alive[idx] || d[idx] < ld || d[idx] >= rd)
    return 0;
  // return s[pos[idx]/SZ].sget(0,0,SZ-1,pos[idx]%SZ,pos[idx]%SZ);
  return tval[pos[idx] % SZ];
}

ll queryb(int idx, int ld, int rd) {
  // printf("queryb(%d,%d,%d)\\n",idx,ld,rd);
  int bl = idx * SZ, br = min(nemp, (idx + 1) * SZ);
  int l = lower_bound(sd + bl, sd + br, ld) - sd;
  if (l >= br || sd[l] >= rd)
    return 0;
  int r = lower_bound(sd + bl, sd + br, rd) - sd;
  // printf("->%d..%d (%d,%d)\\n",l,r-1,bl,br);
  return s[idx].sget(0, 0, SZ - 1, l % SZ, (r - 1) % SZ);
}

ll query(int lid, int rid, int ld, int rd) {
  // printf("query(%d..%d,%d..%d)\\n",lid,rid,ld,rd);
  ll ret = 0;
  if (lid < rid && lid % SZ != 0) {
    int b = lid / SZ;
    s[b].save(0, 0, SZ - 1, tval, tcnt);
    while (lid < rid && lid % SZ != 0)
      ret += query1(emp[lid++], ld, rd);
  }
  if (lid < rid && rid % SZ != 0) {
    int b = rid / SZ;
    s[b].save(0, 0, SZ - 1, tval, tcnt);
    while (lid < rid && rid % SZ != 0)
      ret += query1(emp[--rid], ld, rd);
  }
  while (lid < rid)
    ret += queryb(lid / SZ, ld, rd), lid += SZ;
  return ret;
}

void update1(int idx, int ld, int rd, int by) {
  if (!alive[idx] || d[idx] < ld || d[idx] >= rd)
    return;
  // s[pos[idx]/SZ].smod(0,0,SZ-1,pos[idx]%SZ,pos[idx]%SZ,by);
  tval[pos[idx] % SZ] += by;
}

void updateb(int idx, int ld, int rd, int by) {
  int bl = idx * SZ, br = min(nemp, (idx + 1) * SZ);
  int l = lower_bound(sd + bl, sd + br, ld) - sd;
  if (l >= br || sd[l] >= rd)
    return;
  int r = lower_bound(sd + bl, sd + br, rd) - sd;
  return s[idx].smod(0, 0, SZ - 1, l % SZ, (r - 1) % SZ, by);
}

void update(int lid, int rid, int ld, int rd, int by) {
  if (lid < rid && lid % SZ != 0) {
    int b = lid / SZ;
    s[b].save(0, 0, SZ - 1, tval, tcnt);
    while (lid < rid && lid % SZ != 0)
      update1(emp[lid++], ld, rd, by);
    s[b].load(0, 0, SZ - 1, tval, tcnt);
  }
  if (lid < rid && rid % SZ != 0) {
    int b = rid / SZ;
    s[b].save(0, 0, SZ - 1, tval, tcnt);
    while (lid < rid && rid % SZ != 0)
      update1(emp[--rid], ld, rd, by);
    s[b].load(0, 0, SZ - 1, tval, tcnt);
  }
  while (lid < rid)
    updateb(lid / SZ, ld, rd, by), lid += SZ;
}

void born(int idx) {
  assert(!alive[idx]);
  alive[idx] = true;
  s[pos[idx] / SZ].sborn(0, 0, SZ - 1, pos[idx] % SZ, oval[idx]);
}

ll ans[MAXQ];
void solve() {
  REP(i, nemp) chead[i] = -1;
  REP(i, nemp) if (par[i] != -1) cnxt[i] = chead[par[i]], chead[par[i]] = i;
  nid = 0;
  dfs(0);
  build();

  REP(i, nq) {
    if (qt[i] == 1)
      update(lid[qemp[i]], rid[qemp[i]] + 1, d[qemp[i]], d[qemp[i]] + qd[i] + 1,
             qby[i]);
    if (qt[i] == 2)
      ans[i] = query(lid[qemp[i]], rid[qemp[i]] + 1, d[qemp[i]],
                     d[qemp[i]] + qd[i] + 1);
    if (qt[i] == 3)
      born(qemp[i]);
  }
}

void run() {
  scanf("%d%d", &n, &nq);
  nemp = n;
  REP(i, n) scanf("%d%d", &par[i], &oval[i]), alive[i] = true;
  REP(i, nq) {
    scanf("%d", &qt[i]);
    if (qt[i] == 1)
      scanf("%d%d%d", &qemp[i], &qd[i], &qby[i]);
    if (qt[i] == 2)
      scanf("%d%d", &qemp[i], &qd[i]);
    if (qt[i] == 3)
      scanf("%d%d", &par[nemp], &oval[nemp]), alive[nemp] = false,
                                              qemp[i] = nemp++;
  }
  solve();
  REP(i, nq) if (qt[i] == 2) printf("%lld\\n", ans[i]);
}

void stress() {
  REP(x, 10) {
    n = MAXN;
    nq = MAXQ;
    par[0] = -1;
    FOR(i, 1, n)
    par[i] = i < n / 10 ? i - 1 : (rand() * 1000 + rand()) % (n / 10);
    REP(i, n) oval[i] = rand() % 1000 + 1, alive[i] = true;
    nemp = n;
    REP(i, nq) {
      qt[i] = rand() % 3 + 1;
      if (qt[i] == 1)
        qemp[i] = 0, qd[i] = rand() % (n / 10), qby[i] = rand() % 1000 + 1;
      if (qt[i] == 2)
        qemp[i] = 0, qd[i] = rand() % (n / 10);
      if (qt[i] == 3)
        qemp[i] = nemp, par[nemp] = (rand() * 1000 + rand()) % (n / 10),
        oval[nemp] = rand() % 1000 + 1, alive[nemp] = false, ++nemp;
    }
    clock_t begin = clock();
    solve();
    // REP(i,nq) if(qt[i]==2) printf("%lld\\n",ans[i]); exit(0);
    ll chk = 0;
    REP(i, nq) if (qt[i] == 2) chk += ans[i];
    printf("%.9lf %lld\\n", double(clock() - begin) / CLOCKS_PER_SEC, chk);
  }
}

int main() {
  stress();
  // run();
  return 0;
}

#include <algorithm>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

#define PB push_back
#define MP make_pair
#define SZ(v) ((int)(v).size())
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORE(i, a, b) for (int i = (a); i <= (b); ++i)
#define REPE(i, n) FORE(i, 0, n)
#define FORSZ(i, a, v) FOR(i, a, SZ(v))
#define REPSZ(i, v) REP(i, SZ(v))
typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }

const int MAXN = 400000;
const int MAXQ = 50000;
const int MAXEMP = MAXN + MAXQ;
const int SZ = 400;
const int MAXB = (MAXEMP + SZ - 1) / SZ;

int n, nq, nemp;
int par[MAXEMP], oval[MAXEMP];
bool alive[MAXEMP];
int qt[MAXQ], qemp[MAXQ], qd[MAXQ], qby[MAXQ];

int chead[MAXEMP], cnxt[MAXEMP];
int d[MAXEMP], lid[MAXEMP], rid[MAXEMP], emp[MAXEMP], nid;
void dfs(int at) {
  d[at] = par[at] == -1 ? 0 : d[par[at]] + 1;
  emp[nid] = at, lid[at] = nid++;
  for (int to = chead[at]; to != -1; to = cnxt[to])
    dfs(to);
  rid[at] = nid - 1;
}

int pos[MAXEMP];
int sd[MAXEMP];

typedef struct S {
  ll sval[4 * SZ];
  int slazy[4 * SZ];
  int scnt[4 * SZ];
  void clear() {
    memset(sval, 0, sizeof(sval));
    memset(slazy, 0, sizeof(slazy));
    memset(scnt, 0, sizeof(scnt));
  }
  void spush(int x) {
    if (slazy[x] == 0)
      return;
    sval[2 * x + 1] += slazy[x] * scnt[2 * x + 1];
    slazy[2 * x + 1] += slazy[x];
    sval[2 * x + 2] += slazy[x] * scnt[2 * x + 2];
    slazy[2 * x + 2] += slazy[x];
    slazy[x] = 0;
  }
  void scalc(int x) {
    scnt[x] = scnt[2 * x + 1] + scnt[2 * x + 2];
    sval[x] = sval[2 * x + 1] + sval[2 * x + 2];
  }
  void sborn(int x, int l, int r, int IDX, int VAL) {
    if (l == r) {
      sval[x] = VAL, slazy[x] = 0, scnt[x] = 1;
    } else {
      spush(x);
      int m = l + (r - l) / 2;
      if (IDX <= m)
        sborn(2 * x + 1, l, m, IDX, VAL);
      else
        sborn(2 * x + 2, m + 1, r, IDX, VAL);
      scalc(x);
    }
    // printf("sborn(%d,%d,%d,%d,%d) -> %d
    // %lld\\n",x,l,r,IDX,VAL,scnt[x],sval[x]);
  }
  void smod(int x, int l, int r, int L, int R, int BY) {
    if (L <= l && r <= R) {
      sval[x] += (ll)scnt[x] * BY;
      slazy[x] += BY;
    } else {
      spush(x);
      int m = l + (r - l) / 2;
      if (L <= m)
        smod(2 * x + 1, l, m, L, R, BY);
      if (m + 1 <= R)
        smod(2 * x + 2, m + 1, r, L, R, BY);
      scalc(x);
    }
    // printf("smod(%d,%d,%d,%d,%d,%d) -> %d %lld
    // %d\\n",x,l,r,L,R,BY,scnt[x],sval[x],slazy[x]);
  }
  ll sget(int x, int l, int r, int L, int R) {
    if (L <= l && r <= R) {
      return sval[x];
    } else {
      spush(x);
      int m = l + (r - l) / 2;
      ll ret = 0;
      if (L <= m)
        ret += sget(2 * x + 1, l, m, L, R);
      if (m + 1 <= R)
        ret += sget(2 * x + 2, m + 1, r, L, R);
      return ret;
    }
  }
  void save(int x, int l, int r, ll *val, int *cnt) {
    if (l == r) {
      val[l] = sval[x];
      cnt[l] = scnt[x];
    } else {
      spush(x);
      int m = l + (r - l) / 2;
      save(2 * x + 1, l, m, val, cnt);
      save(2 * x + 2, m + 1, r, val, cnt);
    }
  }
  void load(int x, int l, int r, ll *val, int *cnt) {
    if (l == r) {
      sval[x] = val[l], scnt[x] = cnt[l];
    } else {
      int m = l + (r - l) / 2;
      load(2 * x + 1, l, m, val, cnt);
      load(2 * x + 2, m + 1, r, val, cnt);
      scalc(x);
    }
  }
} S;
S s[MAXB];

int nb;
pair<int, int> tmp[SZ];
void build() {
  for (int i = 0; i < nemp; i += SZ) {
    int cnt = min(SZ, nemp - i);
    REP(j, cnt) tmp[j] = MP(d[emp[i + j]], emp[i + j]);
    sort(tmp, tmp + cnt);
    REP(j, cnt) sd[i + j] = tmp[j].first, pos[tmp[j].second] = i + j;
  }
  nb = (nemp + SZ - 1) / SZ;
  REP(i, nb) s[i].clear();
  REP(i, nemp)
  if (alive[i]) s[pos[i] / SZ].sborn(0, 0, SZ - 1, pos[i] % SZ, oval[i]);
  // REP(i,nemp) printf("%d: emp=%d d=%d pos=%d
  // oval=%d\\n",i,emp[i],d[emp[i]],pos[emp[i]],oval[emp[i]]); REP(i,nemp)
  // printf(" %d",sd[i]); puts("");
}

ll tval[SZ];
int tcnt[SZ];
ll query1(int idx, int ld, int rd) {
  // printf("query1(%d,%d,%d)\\n",idx,ld,rd);
  if (!alive[idx] || d[idx] < ld || d[idx] >= rd)
    return 0;
  // return s[pos[idx]/SZ].sget(0,0,SZ-1,pos[idx]%SZ,pos[idx]%SZ);
  return tval[pos[idx] % SZ];
}

ll queryb(int idx, int ld, int rd) {
  // printf("queryb(%d,%d,%d)\\n",idx,ld,rd);
  int bl = idx * SZ, br = min(nemp, (idx + 1) * SZ);
  int l = lower_bound(sd + bl, sd + br, ld) - sd;
  if (l >= br || sd[l] >= rd)
    return 0;
  int r = lower_bound(sd + bl, sd + br, rd) - sd;
  // printf("->%d..%d (%d,%d)\\n",l,r-1,bl,br);
  return s[idx].sget(0, 0, SZ - 1, l % SZ, (r - 1) % SZ);
}

ll query(int lid, int rid, int ld, int rd) {
  // printf("query(%d..%d,%d..%d)\\n",lid,rid,ld,rd);
  ll ret = 0;
  if (lid < rid && lid % SZ != 0) {
    int b = lid / SZ;
    s[b].save(0, 0, SZ - 1, tval, tcnt);
    while (lid < rid && lid % SZ != 0)
      ret += query1(emp[lid++], ld, rd);
  }
  if (lid < rid && rid % SZ != 0) {
    int b = rid / SZ;
    s[b].save(0, 0, SZ - 1, tval, tcnt);
    while (lid < rid && rid % SZ != 0)
      ret += query1(emp[--rid], ld, rd);
  }
  while (lid < rid)
    ret += queryb(lid / SZ, ld, rd), lid += SZ;
  return ret;
}

void update1(int idx, int ld, int rd, int by) {
  if (!alive[idx] || d[idx] < ld || d[idx] >= rd)
    return;
  // s[pos[idx]/SZ].smod(0,0,SZ-1,pos[idx]%SZ,pos[idx]%SZ,by);
  tval[pos[idx] % SZ] += by;
}

void updateb(int idx, int ld, int rd, int by) {
  int bl = idx * SZ, br = min(nemp, (idx + 1) * SZ);
  int l = lower_bound(sd + bl, sd + br, ld) - sd;
  if (l >= br || sd[l] >= rd)
    return;
  int r = lower_bound(sd + bl, sd + br, rd) - sd;
  return s[idx].smod(0, 0, SZ - 1, l % SZ, (r - 1) % SZ, by);
}

void update(int lid, int rid, int ld, int rd, int by) {
  if (lid < rid && lid % SZ != 0) {
    int b = lid / SZ;
    s[b].save(0, 0, SZ - 1, tval, tcnt);
    while (lid < rid && lid % SZ != 0)
      update1(emp[lid++], ld, rd, by);
    s[b].load(0, 0, SZ - 1, tval, tcnt);
  }
  if (lid < rid && rid % SZ != 0) {
    int b = rid / SZ;
    s[b].save(0, 0, SZ - 1, tval, tcnt);
    while (lid < rid && rid % SZ != 0)
      update1(emp[--rid], ld, rd, by);
    s[b].load(0, 0, SZ - 1, tval, tcnt);
  }
  while (lid < rid)
    updateb(lid / SZ, ld, rd, by), lid += SZ;
}

void born(int idx) {
  assert(!alive[idx]);
  alive[idx] = true;
  s[pos[idx] / SZ].sborn(0, 0, SZ - 1, pos[idx] % SZ, oval[idx]);
}

ll ans[MAXQ];
void solve() {
  REP(i, nemp) chead[i] = -1;
  REP(i, nemp) if (par[i] != -1) cnxt[i] = chead[par[i]], chead[par[i]] = i;
  nid = 0;
  dfs(0);
  build();

  REP(i, nq) {
    if (qt[i] == 1)
      update(lid[qemp[i]], rid[qemp[i]] + 1, d[qemp[i]], d[qemp[i]] + qd[i] + 1,
             qby[i]);
    if (qt[i] == 2)
      ans[i] = query(lid[qemp[i]], rid[qemp[i]] + 1, d[qemp[i]],
                     d[qemp[i]] + qd[i] + 1);
    if (qt[i] == 3)
      born(qemp[i]);
  }
}

void run() {
  scanf("%d%d", &n, &nq);
  nemp = n;
  REP(i, n) scanf("%d%d", &par[i], &oval[i]), alive[i] = true;
  REP(i, nq) {
    scanf("%d", &qt[i]);
    if (qt[i] == 1)
      scanf("%d%d%d", &qemp[i], &qd[i], &qby[i]);
    if (qt[i] == 2)
      scanf("%d%d", &qemp[i], &qd[i]);
    if (qt[i] == 3)
      scanf("%d%d", &par[nemp], &oval[nemp]), alive[nemp] = false,
                                              qemp[i] = nemp++;
  }
  solve();
  REP(i, nq) if (qt[i] == 2) printf("%lld\\n", ans[i]);
}

void stress() {
  REP(x, 10) {
    n = MAXN;
    nq = MAXQ;
    par[0] = -1;
    FOR(i, 1, n)
    par[i] = i < n / 10 ? i - 1 : (rand() * 1000 + rand()) % (n / 10);
    REP(i, n) oval[i] = rand() % 1000 + 1, alive[i] = true;
    nemp = n;
    REP(i, nq) {
      qt[i] = rand() % 3 + 1;
      if (qt[i] == 1)
        qemp[i] = rand() % min(n, 10), qd[i] = rand() % (n / 10),
        qby[i] = rand() % 1000 + 1;
      if (qt[i] == 2)
        qemp[i] = rand() % min(n, 10), qd[i] = rand() % (n / 10);
      if (qt[i] == 3)
        qemp[i] = nemp, par[nemp] = (rand() * 1000 + rand()) % (n / 10),
        oval[nemp] = rand() % 1000 + 1, alive[nemp] = false, ++nemp;
    }
    clock_t begin = clock();
    solve();
    // REP(i,nq) if(qt[i]==2) printf("%lld\\n",ans[i]); exit(0);
    ll chk = 0;
    REP(i, nq) if (qt[i] == 2) chk += ans[i];
    printf("%.9lf %lld\\n", double(clock() - begin) / CLOCKS_PER_SEC, chk);
  }
}

int main() {
  // stress();
  run();
  return 0;
}


#include <algorithm>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

#define PB push_back
#define MP make_pair
#define SZ(v) ((int)(v).size())
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORE(i, a, b) for (int i = (a); i <= (b); ++i)
#define REPE(i, n) FORE(i, 0, n)
#define FORSZ(i, a, v) FOR(i, a, SZ(v))
#define REPSZ(i, v) REP(i, SZ(v))
typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }

const int MAXN = 400000;
const int MAXQ = 50000;
const int MAXEMP = MAXN + MAXQ;
const int SZ = 400;
const int MAXB = (MAXEMP + SZ - 1) / SZ;

int n, nq, nemp;
int par[MAXEMP], oval[MAXEMP];
bool alive[MAXEMP];
int qt[MAXQ], qemp[MAXQ], qd[MAXQ], qby[MAXQ];

int chead[MAXEMP], cnxt[MAXEMP];
int d[MAXEMP], lid[MAXEMP], rid[MAXEMP], emp[MAXEMP], nid;
void dfs(int at) {
  d[at] = par[at] == -1 ? 0 : d[par[at]] + 1;
  emp[nid] = at, lid[at] = nid++;
  for (int to = chead[at]; to != -1; to = cnxt[to])
    dfs(to);
  rid[at] = nid - 1;
}

int pos[MAXEMP];
int sd[MAXEMP];
ll sval[4 * MAXEMP];
int slazy[4 * MAXEMP];
int scnt[4 * MAXEMP];

void spush(int x) {
  if (slazy[x] == 0)
    return;
  sval[2 * x + 1] += slazy[x] * scnt[2 * x + 1];
  slazy[2 * x + 1] += slazy[x];
  sval[2 * x + 2] += slazy[x] * scnt[2 * x + 2];
  slazy[2 * x + 2] += slazy[x];
  slazy[x] = 0;
}
void scalc(int x) {
  scnt[x] = scnt[2 * x + 1] + scnt[2 * x + 2];
  sval[x] = sval[2 * x + 1] + sval[2 * x + 2];
}
void sborn(int x, int l, int r, int IDX, int VAL) {
  if (l == r) {
    sval[x] = VAL, slazy[x] = 0, scnt[x] = 1;
  } else {
    spush(x);
    int m = l + (r - l) / 2;
    if (IDX <= m)
      sborn(2 * x + 1, l, m, IDX, VAL);
    else
      sborn(2 * x + 2, m + 1, r, IDX, VAL);
    scalc(x);
  }
  // printf("sborn(%d,%d,%d,%d,%d) -> %d %lld\\n",x,l,r,IDX,VAL,scnt[x],sval[x]);
}
void smod(int x, int l, int r, int L, int R, int BY) {
  if (L <= l && r <= R) {
    sval[x] += (ll)scnt[x] * BY;
    slazy[x] += BY;
  } else {
    spush(x);
    int m = l + (r - l) / 2;
    if (L <= m)
      smod(2 * x + 1, l, m, L, R, BY);
    if (m + 1 <= R)
      smod(2 * x + 2, m + 1, r, L, R, BY);
    scalc(x);
  }
  // printf("smod(%d,%d,%d,%d,%d,%d) -> %d %lld
  // %d\\n",x,l,r,L,R,BY,scnt[x],sval[x],slazy[x]);
}
ll sget(int x, int l, int r, int L, int R) {
  if (L <= l && r <= R) {
    return sval[x];
  } else {
    spush(x);
    int m = l + (r - l) / 2;
    ll ret = 0;
    if (L <= m)
      ret += sget(2 * x + 1, l, m, L, R);
    if (m + 1 <= R)
      ret += sget(2 * x + 2, m + 1, r, L, R);
    return ret;
  }
}

pair<int, int> tmp[SZ];
void build() {
  for (int i = 0; i < nemp; i += SZ) {
    int cnt = min(SZ, nemp - i);
    REP(j, cnt) tmp[j] = MP(d[emp[i + j]], emp[i + j]);
    sort(tmp, tmp + cnt);
    REP(j, cnt) sd[i + j] = tmp[j].first, pos[tmp[j].second] = i + j;
  }
  memset(sval, 0, sizeof(sval));
  memset(slazy, 0, sizeof(slazy));
  memset(scnt, 0, sizeof(scnt));
  REP(i, nemp) if (alive[i]) sborn(0, 0, nemp - 1, pos[i], oval[i]);
  // REP(i,nemp) printf("%d: emp=%d d=%d pos=%d
  // oval=%d\\n",i,emp[i],d[emp[i]],pos[emp[i]],oval[emp[i]]); REP(i,nemp)
  // printf(" %d",sd[i]); puts("");
}

ll query1(int idx, int ld, int rd) {
  // printf("query1(%d,%d,%d)\\n",idx,ld,rd);
  if (!alive[idx] || d[idx] < ld || d[idx] >= rd)
    return 0;
  return sget(0, 0, nemp - 1, pos[idx], pos[idx]);
}

ll queryb(int idx, int ld, int rd) {
  // printf("queryb(%d,%d,%d)\\n",idx,ld,rd);
  int bl = idx * SZ, br = min(nemp, (idx + 1) * SZ);
  int l = lower_bound(sd + bl, sd + br, ld) - sd;
  if (l >= br || sd[l] >= rd)
    return 0;
  int r = lower_bound(sd + bl, sd + br, rd) - sd;
  // printf("->%d..%d (%d,%d)\\n",l,r-1,bl,br);
  return sget(0, 0, nemp - 1, l, r - 1);
}

ll query(int lid, int rid, int ld, int rd) {
  // printf("query(%d..%d,%d..%d)\\n",lid,rid,ld,rd);
  ll ret = 0;
  while (lid < rid && lid % SZ != 0)
    ret += query1(emp[lid++], ld, rd);
  while (lid < rid && rid % SZ != 0)
    ret += query1(emp[--rid], ld, rd);
  while (lid < rid)
    ret += queryb(lid / SZ, ld, rd), lid += SZ;
  return ret;
}

void update1(int idx, int ld, int rd, int by) {
  if (!alive[idx] || d[idx] < ld || d[idx] >= rd)
    return;
  smod(0, 0, nemp - 1, pos[idx], pos[idx], by);
}

void updateb(int idx, int ld, int rd, int by) {
  int bl = idx * SZ, br = min(nemp, (idx + 1) * SZ);
  int l = lower_bound(sd + bl, sd + br, ld) - sd;
  if (l >= br || sd[l] >= rd)
    return;
  int r = lower_bound(sd + bl, sd + br, rd) - sd;
  return smod(0, 0, nemp - 1, l, r - 1, by);
}

void update(int lid, int rid, int ld, int rd, int by) {
  while (lid < rid && lid % SZ != 0)
    update1(emp[lid++], ld, rd, by);
  while (lid < rid && rid % SZ != 0)
    update1(emp[--rid], ld, rd, by);
  while (lid < rid)
    updateb(lid / SZ, ld, rd, by), lid += SZ;
}

void born(int idx) {
  assert(!alive[idx]);
  alive[idx] = true;
  sborn(0, 0, nemp - 1, pos[idx], oval[idx]);
}

ll ans[MAXQ];
void solve() {
  REP(i, nemp) chead[i] = -1;
  REP(i, nemp) if (par[i] != -1) cnxt[i] = chead[par[i]], chead[par[i]] = i;
  nid = 0;
  dfs(0);
  build();

  REP(i, nq) {
    if (qt[i] == 1)
      update(lid[qemp[i]], rid[qemp[i]] + 1, d[qemp[i]], d[qemp[i]] + qd[i] + 1,
             qby[i]);
    if (qt[i] == 2)
      ans[i] = query(lid[qemp[i]], rid[qemp[i]] + 1, d[qemp[i]],
                     d[qemp[i]] + qd[i] + 1);
    if (qt[i] == 3)
      born(qemp[i]);
  }
}

void run() {
  scanf("%d%d", &n, &nq);
  nemp = n;
  REP(i, n) scanf("%d%d", &par[i], &oval[i]), alive[i] = true;
  REP(i, nq) {
    scanf("%d", &qt[i]);
    if (qt[i] == 1)
      scanf("%d%d%d", &qemp[i], &qd[i], &qby[i]);
    if (qt[i] == 2)
      scanf("%d%d", &qemp[i], &qd[i]);
    if (qt[i] == 3)
      scanf("%d%d", &par[nemp], &oval[nemp]), alive[nemp] = false,
                                              qemp[i] = nemp++;
  }
  solve();
  REP(i, nq) if (qt[i] == 2) printf("%lld\\n", ans[i]);
}

void stress() {
  REP(x, 10) {
    n = MAXN;
    nq = MAXQ;
    par[0] = -1;
    FOR(i, 1, n) par[i] = rand() % i;
    REP(i, n) oval[i] = rand() % 1000 + 1, alive[i] = true;
    nemp = n;
    REP(i, nq) {
      qt[i] = rand() % 3 + 1;
      if (qt[i] == 1)
        qemp[i] = rand() % min(50, nemp), qd[i] = rand() % 100,
        qby[i] = rand() % 1000 + 1;
      if (qt[i] == 2)
        qemp[i] = rand() % min(50, nemp), qd[i] = rand() % 100;
      if (qt[i] == 3)
        qemp[i] = nemp, par[nemp] = rand() % nemp,
        oval[nemp] = rand() % 1000 + 1, alive[nemp] = false, ++nemp;
    }
    clock_t begin = clock();
    solve();
    printf("%.9lf\\n", double(clock() - begin) / CLOCKS_PER_SEC);
  }
}

int main() {
  // stress();
  run();
  return 0;
}

#include <algorithm>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <iostream>
#include <list>
#include <map>
#include <queue>
#include <set>
#include <sstream>
#include <string>
#include <vector>
using namespace std;

#define PB push_back
#define MP make_pair
#define SZ(v) ((int)(v).size())
#define FOR(i, a, b) for (int i = (a); i < (b); ++i)
#define REP(i, n) FOR(i, 0, n)
#define FORE(i, a, b) for (int i = (a); i <= (b); ++i)
#define REPE(i, n) FORE(i, 0, n)
#define FORSZ(i, a, v) FOR(i, a, SZ(v))
#define REPSZ(i, v) REP(i, SZ(v))
typedef long long ll;
typedef unsigned long long ull;
ll gcd(ll a, ll b) { return b == 0 ? a : gcd(b, a % b); }

const int MAXN = 400000;
const int MAXQ = 50000;
const int MAXEMP = MAXN + MAXQ;
const int SZ = 400;
const int MAXB = (MAXEMP + SZ - 1) / SZ;

int n, nq, nemp;
int par[MAXEMP], oval[MAXEMP];
bool alive[MAXEMP];
int qt[MAXQ], qemp[MAXQ], qd[MAXQ], qby[MAXQ];

int chead[MAXEMP], cnxt[MAXEMP];
int d[MAXEMP], lid[MAXEMP], rid[MAXEMP], emp[MAXEMP], nid;
void dfs(int at) {
  d[at] = par[at] == -1 ? 0 : d[par[at]] + 1;
  emp[nid] = at, lid[at] = nid++;
  for (int to = chead[at]; to != -1; to = cnxt[to])
    dfs(to);
  rid[at] = nid - 1;
}

int pos[MAXEMP];
int sd[MAXEMP];

typedef struct S {
  ll sval[4 * SZ];
  int slazy[4 * SZ];
  int scnt[4 * SZ];
  void clear() {
    memset(sval, 0, sizeof(sval));
    memset(slazy, 0, sizeof(slazy));
    memset(scnt, 0, sizeof(scnt));
  }
  void spush(int x) {
    if (slazy[x] == 0)
      return;
    sval[2 * x + 1] += slazy[x] * scnt[2 * x + 1];
    slazy[2 * x + 1] += slazy[x];
    sval[2 * x + 2] += slazy[x] * scnt[2 * x + 2];
    slazy[2 * x + 2] += slazy[x];
    slazy[x] = 0;
  }
  void scalc(int x) {
    scnt[x] = scnt[2 * x + 1] + scnt[2 * x + 2];
    sval[x] = sval[2 * x + 1] + sval[2 * x + 2];
  }
  void sborn(int x, int l, int r, int IDX, int VAL) {
    if (l == r) {
      sval[x] = VAL, slazy[x] = 0, scnt[x] = 1;
    } else {
      spush(x);
      int m = l + (r - l) / 2;
      if (IDX <= m)
        sborn(2 * x + 1, l, m, IDX, VAL);
      else
        sborn(2 * x + 2, m + 1, r, IDX, VAL);
      scalc(x);
    }
    // printf("sborn(%d,%d,%d,%d,%d) -> %d
    // %lld\\n",x,l,r,IDX,VAL,scnt[x],sval[x]);
  }
  void smod(int x, int l, int r, int L, int R, int BY) {
    if (L <= l && r <= R) {
      sval[x] += (ll)scnt[x] * BY;
      slazy[x] += BY;
    } else {
      spush(x);
      int m = l + (r - l) / 2;
      if (L <= m)
        smod(2 * x + 1, l, m, L, R, BY);
      if (m + 1 <= R)
        smod(2 * x + 2, m + 1, r, L, R, BY);
      scalc(x);
    }
    // printf("smod(%d,%d,%d,%d,%d,%d) -> %d %lld
    // %d\\n",x,l,r,L,R,BY,scnt[x],sval[x],slazy[x]);
  }
  ll sget(int x, int l, int r, int L, int R) {
    if (L <= l && r <= R) {
      return sval[x];
    } else {
      spush(x);
      int m = l + (r - l) / 2;
      ll ret = 0;
      if (L <= m)
        ret += sget(2 * x + 1, l, m, L, R);
      if (m + 1 <= R)
        ret += sget(2 * x + 2, m + 1, r, L, R);
      return ret;
    }
  }
} S;
S s[MAXB];

int nb;
pair<int, int> tmp[SZ];
void build() {
  for (int i = 0; i < nemp; i += SZ) {
    int cnt = min(SZ, nemp - i);
    REP(j, cnt) tmp[j] = MP(d[emp[i + j]], emp[i + j]);
    sort(tmp, tmp + cnt);
    REP(j, cnt) sd[i + j] = tmp[j].first, pos[tmp[j].second] = i + j;
  }
  nb = (nemp + SZ - 1) / SZ;
  REP(i, nb) s[i].clear();
  REP(i, nemp)
  if (alive[i]) s[pos[i] / SZ].sborn(0, 0, SZ - 1, pos[i] % SZ, oval[i]);
  // REP(i,nemp) printf("%d: emp=%d d=%d pos=%d
  // oval=%d\\n",i,emp[i],d[emp[i]],pos[emp[i]],oval[emp[i]]); REP(i,nemp)
  // printf(" %d",sd[i]); puts("");
}

ll query1(int idx, int ld, int rd) {
  // printf("query1(%d,%d,%d)\\n",idx,ld,rd);
  if (!alive[idx] || d[idx] < ld || d[idx] >= rd)
    return 0;
  return s[pos[idx] / SZ].sget(0, 0, SZ - 1, pos[idx] % SZ, pos[idx] % SZ);
}

ll queryb(int idx, int ld, int rd) {
  // printf("queryb(%d,%d,%d)\\n",idx,ld,rd);
  int bl = idx * SZ, br = min(nemp, (idx + 1) * SZ);
  int l = lower_bound(sd + bl, sd + br, ld) - sd;
  if (l >= br || sd[l] >= rd)
    return 0;
  int r = lower_bound(sd + bl, sd + br, rd) - sd;
  // printf("->%d..%d (%d,%d)\\n",l,r-1,bl,br);
  return s[idx].sget(0, 0, SZ - 1, l % SZ, (r - 1) % SZ);
}

ll query(int lid, int rid, int ld, int rd) {
  // printf("query(%d..%d,%d..%d)\\n",lid,rid,ld,rd);
  ll ret = 0;
  while (lid < rid && lid % SZ != 0)
    ret += query1(emp[lid++], ld, rd);
  while (lid < rid && rid % SZ != 0)
    ret += query1(emp[--rid], ld, rd);
  while (lid < rid)
    ret += queryb(lid / SZ, ld, rd), lid += SZ;
  return ret;
}

void update1(int idx, int ld, int rd, int by) {
  if (!alive[idx] || d[idx] < ld || d[idx] >= rd)
    return;
  s[pos[idx] / SZ].smod(0, 0, SZ - 1, pos[idx] % SZ, pos[idx] % SZ, by);
}

void updateb(int idx, int ld, int rd, int by) {
  int bl = idx * SZ, br = min(nemp, (idx + 1) * SZ);
  int l = lower_bound(sd + bl, sd + br, ld) - sd;
  if (l >= br || sd[l] >= rd)
    return;
  int r = lower_bound(sd + bl, sd + br, rd) - sd;
  return s[idx].smod(0, 0, SZ - 1, l % SZ, (r - 1) % SZ, by);
}

void update(int lid, int rid, int ld, int rd, int by) {
  while (lid < rid && lid % SZ != 0)
    update1(emp[lid++], ld, rd, by);
  while (lid < rid && rid % SZ != 0)
    update1(emp[--rid], ld, rd, by);
  while (lid < rid)
    updateb(lid / SZ, ld, rd, by), lid += SZ;
}

void born(int idx) {
  assert(!alive[idx]);
  alive[idx] = true;
  s[pos[idx] / SZ].sborn(0, 0, SZ - 1, pos[idx] % SZ, oval[idx]);
}

ll ans[MAXQ];
void solve() {
  REP(i, nemp) chead[i] = -1;
  REP(i, nemp) if (par[i] != -1) cnxt[i] = chead[par[i]], chead[par[i]] = i;
  nid = 0;
  dfs(0);
  build();

  REP(i, nq) {
    if (qt[i] == 1)
      update(lid[qemp[i]], rid[qemp[i]] + 1, d[qemp[i]], d[qemp[i]] + qd[i] + 1,
             qby[i]);
    if (qt[i] == 2)
      ans[i] = query(lid[qemp[i]], rid[qemp[i]] + 1, d[qemp[i]],
                     d[qemp[i]] + qd[i] + 1);
    if (qt[i] == 3)
      born(qemp[i]);
  }
}

void run() {
  scanf("%d%d", &n, &nq);
  nemp = n;
  REP(i, n) scanf("%d%d", &par[i], &oval[i]), alive[i] = true;
  REP(i, nq) {
    scanf("%d", &qt[i]);
    if (qt[i] == 1)
      scanf("%d%d%d", &qemp[i], &qd[i], &qby[i]);
    if (qt[i] == 2)
      scanf("%d%d", &qemp[i], &qd[i]);
    if (qt[i] == 3)
      scanf("%d%d", &par[nemp], &oval[nemp]), alive[nemp] = false,
                                              qemp[i] = nemp++;
  }
  solve();
  REP(i, nq) if (qt[i] == 2) printf("%lld\\n", ans[i]);
}

void stress() {
  REP(x, 10) {
    n = MAXN;
    nq = MAXQ;
    par[0] = -1;
    FOR(i, 1, n)
    par[i] = i < n / 10 ? i - 1 : (rand() * 1000 + rand()) % (n / 10);
    REP(i, n) oval[i] = rand() % 1000 + 1, alive[i] = true;
    nemp = n;
    REP(i, nq) {
      qt[i] = rand() % 3 + 1;
      if (qt[i] == 1)
        qemp[i] = 0, qd[i] = rand() % (n / 10), qby[i] = rand() % 1000 + 1;
      if (qt[i] == 2)
        qemp[i] = 0, qd[i] = rand() % (n / 10);
      if (qt[i] == 3)
        qemp[i] = nemp, par[nemp] = (rand() * 1000 + rand()) % (n / 10),
        oval[nemp] = rand() % 1000 + 1, alive[nemp] = false, ++nemp;
    }
    clock_t begin = clock();
    solve();
    printf("%.9lf\\n", double(clock() - begin) / CLOCKS_PER_SEC);
  }
}

int main() {
  // stress();
  run();
  return 0;
}