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;
const int maxn = 200005;
const int mlog = 20;
int n, q, mx;
int w[maxn], v[maxn], p[maxn], ip[maxn], rt[maxn];
long long a[maxn];
vector<int> pos[maxn];
bool cmp(int x, int y) {
  if (v[x] != v[y])
    return v[x] > v[y];
  else
    return w[x] < w[y];
}
class Segtree1 {
 public:
  long long sumw[maxn * 4], sumv[maxn * 4];
  void update(int cur, int l, int r, int k) {
    if (l == r) {
      sumw[cur] = a[p[l]] * w[p[l]];
      sumv[cur] = a[p[l]] * v[p[l]];
      return;
    }
    int mid = l + r >> 1;
    if (k <= mid)
      update(cur << 1, l, mid, k);
    else
      update(cur << 1 | 1, mid + 1, r, k);
    sumw[cur] = sumw[cur << 1] + sumw[cur << 1 | 1];
    sumv[cur] = sumv[cur << 1] + sumv[cur << 1 | 1];
  }
  int query(int cur, int l, int r, int vl, int vr, long long &val,
            long long &ans) {
    if (l >= vl && r <= vr && sumw[cur] <= val) {
      val -= sumw[cur];
      ans += sumv[cur];
      return vr + 1;
    }
    if (l == r) return l;
    int mid = l + r >> 1;
    int res = mid >= vl ? query(cur << 1, l, mid, vl, vr, val, ans) : vr + 1;
    if (res <= vr)
      return res;
    else
      return mid < vr ? query(cur << 1 | 1, mid + 1, r, vl, vr, val, ans)
                      : vr + 1;
  }
} Tree[mlog];
namespace Segtree2 {
const int maxv = maxn * 40;
int tot;
int ls[maxv], rs[maxv], cnt[maxv];
void insert(int &cur1, int cur2, int l, int r, int k) {
  cur1 = ++tot;
  ls[cur1] = ls[cur2];
  rs[cur1] = rs[cur2];
  cnt[cur1] = cnt[cur2] + 1;
  if (l == r) return;
  int mid = l + r >> 1;
  if (k <= mid)
    insert(ls[cur1], ls[cur2], l, mid, k);
  else
    insert(rs[cur1], rs[cur2], mid + 1, r, k);
}
int findp(int cur1, int cur2, int l, int r, int vl, int vr) {
  if (vl > vr) return vr + 1;
  if (l >= vl && r <= vr && cnt[cur1] == cnt[cur2]) return vr + 1;
  if (l == r) return l;
  int mid = l + r >> 1;
  int res = mid >= vl ? findp(ls[cur1], ls[cur2], l, mid, vl, vr) : vr + 1;
  if (res <= vr)
    return res;
  else
    return mid < vr ? findp(rs[cur1], rs[cur2], mid + 1, r, vl, vr) : vr + 1;
}
}  // namespace Segtree2
void modify(int x) {
  for (int i = 0; i < mlog; i++)
    if (w[x] < (1 << i)) Tree[i].update(1, 1, n, ip[x]);
}
long long answer(long long c) {
  long long ans = 0;
  int pt = 1;
  for (int i = mlog - 1; i >= 0; i--)
    if (c >= (1 << i)) {
      long long val = c - (1 << i);
      int rpt = Segtree2::findp(rt[min(mx, (1 << i) - 1)],
                                rt[min((long long)mx, c)], 1, n, pt, n);
      if (rpt > pt) pt = Tree[i].query(1, 1, n, pt, rpt - 1, val, ans);
      c = (1 << i) + val;
      if (pt <= n) {
        long long d = min(a[p[pt]], c / w[p[pt]]);
        c -= d * w[p[pt]];
        ans += d * v[p[pt]];
        pt++;
      }
      if (pt > n) break;
    }
  return ans;
}
int main() {
  scanf("%d%d", &n, &q);
  for (int i = 1; i <= n; i++) {
    scanf("%lld%d%d", &a[i], &w[i], &v[i]);
    p[i] = i;
    mx = max(mx, w[i]);
  }
  sort(p + 1, p + 1 + n, cmp);
  for (int i = 1; i <= n; i++) {
    ip[p[i]] = i;
    pos[w[p[i]]].push_back(i);
  }
  for (int i = 1; i <= mx; i++) {
    rt[i] = rt[i - 1];
    for (int j = 0; j < int(pos[i].size()); j++)
      Segtree2::insert(rt[i], rt[i], 1, n, pos[i][j]);
  }
  for (int i = 1; i <= n; i++) modify(i);
  while (q--) {
    int op;
    scanf("%d", &op);
    if (op == 1) {
      int b, x;
      scanf("%d%d", &b, &x);
      a[x] += b;
      modify(x);
    } else if (op == 2) {
      int b, x;
      scanf("%d%d", &b, &x);
      a[x] -= b;
      modify(x);
    } else {
      long long c;
      scanf("%lld", &c);
      printf("%lld\n", answer(c));
    }
  }
  return 0;
}
