2 8
2 15 400
1 13 100
3 26
3 27
3 28
3 29
3 30
3 31
3 32
3 33
 3 8
2 15 400
1 1 200
1 13 100
3 26
3 27
3 28
3 29
3 30
3 31
3 32
3 33

400
400
500
500
800
800
800
800
 600
600
600
700
800
1000
1000
1000

#include <bits/stdc++.h>
using namespace std;
template <typename A, typename B>
string to_string(pair<A, B> p);
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p);
template <typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p);
string to_string(const string& s) { return '"' + s + '"'; }
string to_string(const char* s) { return to_string((string)s); }
string to_string(bool b) { return (b ? "true" : "false"); }
string to_string(vector<bool> v) {
  bool first = true;
  string res = "{";
  for (int i = 0; i < static_cast<int>(v.size()); i++) {
    if (!first) {
      res += ", ";
    }
    first = false;
    res += to_string(v[i]);
  }
  res += "}";
  return res;
}
template <size_t N>
string to_string(bitset<N> v) {
  string res = "";
  for (size_t i = 0; i < N; i++) {
    res += static_cast<char>('0' + v[i]);
  }
  return res;
}
template <typename A>
string to_string(A v) {
  bool first = true;
  string res = "{";
  for (const auto& x : v) {
    if (!first) {
      res += ", ";
    }
    first = false;
    res += to_string(x);
  }
  res += "}";
  return res;
}
template <typename A, typename B>
string to_string(pair<A, B> p) {
  return "(" + to_string(p.first) + ", " + to_string(p.second) + ")";
}
template <typename A, typename B, typename C>
string to_string(tuple<A, B, C> p) {
  return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " +
         to_string(get<2>(p)) + ")";
}
template <typename A, typename B, typename C, typename D>
string to_string(tuple<A, B, C, D> p) {
  return "(" + to_string(get<0>(p)) + ", " + to_string(get<1>(p)) + ", " +
         to_string(get<2>(p)) + ", " + to_string(get<3>(p)) + ")";
}
void debug_out() { cerr << endl; }
template <typename Head, typename... Tail>
void debug_out(Head H, Tail... T) {
  cerr << " " << to_string(H);
  debug_out(T...);
}
template <typename T>
void read(T& x) {
  x = 0;
  char ch = getchar();
  long long f = 1;
  while (!isdigit(ch)) {
    if (ch == '-') f *= -1;
    ch = getchar();
  }
  while (isdigit(ch)) {
    x = x * 10 + ch - 48;
    ch = getchar();
  }
  x *= f;
}
template <typename T, typename... Args>
void read(T& first, Args&... args) {
  read(first);
  read(args...);
}
int n, q, a[200020], w[200020], v[200020];
int id[200020], rid[200020];
long long aa[200020], vv[200020], ww[200020];
const int SZ = 19;
long long sv[525000][SZ], sw[525000][SZ];
multiset<int> second[525000][SZ];
inline int l2(long long x) { return 64 - __builtin_clzl(x); }
void build_tree(int l, int r, int id) {
  if (l == r) {
    int c = l2(ww[l]);
    for (int i = c; i < SZ; i++) {
      sv[id][i] = aa[l] * vv[l];
      sw[id][i] = aa[l] * ww[l];
    }
    if (aa[l]) second[id][c].insert(ww[l]);
    return;
  }
  build_tree(l, ((l + r) / 2), id * 2);
  build_tree(((l + r) / 2) + 1, r, id * 2 + 1);
  for (int i = 0; i < SZ; i++) {
    sw[id][i] = sw[id * 2][i] + sw[id * 2 + 1][i];
    sv[id][i] = sv[id * 2][i] + sv[id * 2 + 1][i];
    for (auto ct : second[i][id * 2]) second[id][i].insert(ct);
    for (auto ct : second[i][id * 2 + 1]) second[id][i].insert(ct);
  }
}
pair<int, int> op(int l, int r, int id, int q, int ch) {
  if (l == r) {
    pair<int, int> ret;
    if (aa[l] > 0 && aa[l] + ch == 0) ret = make_pair(-1, ww[l]);
    if (aa[l] == 0 && aa[l] + ch > 0) ret = make_pair(1, ww[l]);
    int c = l2(ww[l]);
    if (aa[l]) second[id][c].erase(ww[l]);
    aa[l] += ch;
    for (int i = c; i < SZ; i++) {
      sv[id][i] = aa[l] * vv[l];
      sw[id][i] = aa[l] * ww[l];
    }
    if (aa[l]) second[id][c].insert(ww[l]);
    return ret;
  }
  pair<int, int> cr;
  if (q <= ((l + r) / 2))
    cr = op(l, ((l + r) / 2), id * 2, q, ch);
  else
    cr = op(((l + r) / 2) + 1, r, id * 2 + 1, q, ch);
  for (int i = 0; i < SZ; i++) {
    sw[id][i] = sw[id * 2][i] + sw[id * 2 + 1][i];
    sv[id][i] = sv[id * 2][i] + sv[id * 2 + 1][i];
  }
  if (cr.first == 1) second[id][l2(cr.second)].insert(cr.second);
  if (cr.first == -1) second[id][l2(cr.second)].erase(cr.second);
  return cr;
}
pair<long long, long long> query(int l, int r, int id, long long rem) {
  if (rem == 0) return make_pair(0, 0);
  if (l == r) {
    long long cnt = min(aa[l], (rem / ww[l]));
    return make_pair(cnt * vv[l], rem - cnt * ww[l]);
  }
  int c = min(SZ - 1, l2(rem));
  int ok = 0;
  if (second[id][c].size())
    if (*(second[id][c].begin()) <= rem) ok = 1;
  if (!ok && rem >= sw[id][c - 1])
    return make_pair(sv[id][c - 1], rem - sw[id][c - 1]);
  pair<long long, long long> ret = query(((l + r) / 2) + 1, r, id * 2 + 1, rem);
  pair<long long, long long> cc = query(l, ((l + r) / 2), id * 2, ret.second);
  ret.second = cc.second;
  ret.first += cc.first;
  return ret;
}
int main() {
  read(n, q);
  vector<pair<pair<int, int>, int>> V;
  for (int i = 1; i <= n; i++) {
    read(a[i], w[i], v[i]);
    V.push_back(make_pair(make_pair(v[i], -w[i]), i));
  }
  sort(V.begin(), V.end());
  for (int i = 0; i < n; i++) {
    id[V[i].second] = i;
    rid[i] = V[i].second;
    aa[i] = a[V[i].second];
    vv[i] = v[V[i].second];
    ww[i] = w[V[i].second];
  }
  build_tree(0, n - 1, 1);
  int t, k, d;
  for (int i = 0; i < q; i++) {
    read(t);
    if (t == 1) {
      read(d, k);
      op(0, n - 1, 1, id[k], d);
    }
    if (t == 2) {
      read(d, k);
      op(0, n - 1, 1, id[k], -d);
    }
    if (t == 3) {
      long long lim;
      read(lim);
      cout << query(0, n - 1, 1, lim).first << "\n";
    }
  }
  return 0;
}
