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

/*
  Author: dendi239
  Time:   2021-05-10 17:44:21
*/

#include <bits/stdc++.h>

#define requires(...) typename std::enable_if<__VA_ARGS__::value, int>::type = 0

using namespace std;

template<class U, class V>
istream &operator>>(istream &is, pair<U, V> &p) { return is >> p.first >> p.second; }

template<class U, class V>
ostream &operator<<(ostream &os, const pair<U, V> &p) {
  return os << "(" << p.first << ", " << p.second << ")";
}

template<class Istream, class Container, requires(is_same<Istream, istream>)>
Istream &operator>>(Istream &is, Container &container) {
  for (auto &value : container) is >> value;
  return is;
}

template<class Ostream, class Container, requires(is_same<Ostream, ostream>)>
Ostream &operator<<(Ostream &os, const Container &container) {
  auto _begin = begin(container), _end = end(container);
  for (auto it = _begin; it != _end;)
  os << "{ "[it != _begin] << *it << ",}"[++it == _end];
  return os;
}

namespace io {
  template <class ...As> struct last {};
  template <class ...As> using last_t = typename last<As...>::type;
  template <class A> struct last<A> { using type = A; };
  template <class A, class ...As> struct last<A, As...> {
    using type = typename last<As...>::type;
  };

  template <class Z>
  Z read(Z &) { Z z; cin >> z; return z; }

  template <class A, class ...As>
  last_t<As...> read(A &a, As &...as) { return cin >> a, read(as...); }

  void log_rest() {}

  template <class A, class ...As>
  void log_rest(const A &a, const As &...as) { cerr << ", " << a; log_rest(as...); }

  template<class A, class ...As>
  void log(const string &pref, const A &a, const As &...as)
  { cerr << pref << a, log_rest(as...); }
}  // namespace io

#define A(xs) begin(xs), end(xs)
#define B(...) [&](auto &&lhs, auto &&rhs) { \
    return __VA_ARGS__;                      \
  }
#define U(...) [&](auto &&lhs, auto &&rhs) { \
  auto predicate = [&](auto &&x) {           \
    return __VA_ARGS__;                      \
  };                                         \
  return predicate(lhs) < predicate(rhs);    \
}
#define X  first
#define Y  second
#define PB push_back
#define EB emplace_back

#define R(...)        __VA_ARGS__ = io::read(__VA_ARGS__)
#define RC(name, ...) name(__VA_ARGS__); cin >> name

#define G3(_1, _2, _3, FUNC, ...) FUNC
#define F1(i, n)    for (typename remove_cv<decltype(n)>::type i = {}; i != n; ++i)
#define F2(i, a, b) for (typename common_type<decltype(a), decltype(b)>::type \
                         down = a > b, i = a - down; i + down != b;           \
                         down ? --i : ++i)

#define F(...) G3(__VA_ARGS__, F2, F1)(__VA_ARGS__)

#ifdef DEBUG
int recursion_depth = 0;
#  define D       for (bool _flag = true; _flag; _flag = !_flag)
#  define L(...)  (++recursion_depth,                  \
    io::log(string(recursion_depth - 1, '\t') +        \
        string(__func__) + ":" + to_string(__LINE__) + \
        " \t( "#__VA_ARGS__" ) := ",                   \
        __VA_ARGS__),                                  \
    --recursion_depth, cerr << "\n")
#  define dbg(...) [&](const string &func) -> auto && { \
      ++recursion_depth;                                \
      auto&& value = __VA_ARGS__;                       \
      --recursion_depth;                                \
      cerr << string(recursion_depth, '\t')             \
           << func << ":" << __LINE__                   \
           << " \t"#__VA_ARGS__" = " << value << endl;  \
      return forward<decltype(value)>(value);           \
    }(__func__)
#else
#  define L(...)   while (false) cerr
#  define D        while (false)
#  define dbg(...) (__VA_ARGS__)
#endif

template<class T>
T make_vec(T default_value) { return default_value; }

template<class T, class Arg, class ...Args>
auto make_vec(T default_value, Arg size, Args ...rest)
-> vector<decltype(make_vec(default_value, rest...))> {
  auto level = make_vec(default_value, rest...);
  return vector<decltype(level)>(size, level);
}

template<class Xs> int len(const Xs &xs) { return static_cast<int>(xs.size()); }

using i64 = int64_t;
using f80 = long double;

using Str = string;
template<class T = int> using Vec = vector<T>;
template<class K = int, class H = hash<K>> using US = unordered_set<K, H>;
template<class K, class V, class H = hash<K>> using UM = unordered_map<K, V, H>;

template<class U = int, class V = U> using P = pair<U, V>;
using G = Vec<Vec<int>>;

template <class T, class P>
auto bin_search(T l, T r, P p) -> T {
  for (T m; m = (l + r) / 2, m != l && m != r; (p(m) ? l : r) = m);
  return l;
}

struct Diamond {
  int count;
  int weight, cost;

  bool operator<(const Diamond &rhs) const {
    if (cost != rhs.cost) {
      return cost < rhs.cost;
    }
    return weight > rhs.weight;
  }
};

istream &operator>>(istream &is, Diamond &d) {
  return is >> d.count >> d.weight >> d.cost;
}

struct Limited {
  i64 value;

  Limited(i64 value = 0) : value{value} {}
  explicit operator i64() const {
    return value;
  }

  static const i64 kLimit;
  static const Limited kMax;

  Limited operator+(const Limited &rhs) const {
    if (value > kLimit - rhs.value) {
      return kMax;
    } else {
      return Limited{value + rhs.value};
    }
  }

  Limited operator*(const Limited &rhs) const {
    if (rhs.value != 0 && value > kLimit / rhs.value) {
      return kMax;
    } else {
      return Limited{value * rhs.value};
    }
  }
};

bool operator<(const Limited &lhs, const Limited &rhs) {
  return lhs.value < rhs.value;
}

const i64 Limited::kLimit = 1'000'000'000'000'000'009LL;
const Limited Limited::kMax = Limited(Limited::kLimit);

Limited operator""_l(unsigned long long value) {
  return Limited{static_cast<i64>(value)};
}

mt19937 rnd;

struct Node {
  Limited total_weight = 0, total_cost = 0;
  Diamond *diamond = nullptr;

  int priority = rnd();
  Node *parent = nullptr;
  Node *left = nullptr, *right = nullptr;
};

Limited Weight(Node *node) {
  if (!node) return 0;
  return node->total_weight;
}

Limited Cost(Node *node) {
  if (!node) return 0;
  return node->total_cost;
}

Limited NodeCost(Node *node) {
  return 1_l * node->diamond->cost * node->diamond->count;
}

Limited NodeWeight(Node *node) {
  return 1_l * node->diamond->weight * node->diamond->count;
}

Node *Update(Node *node) {
  node->total_cost = NodeCost(node)
    + Cost(node->left)
    + Cost(node->right);
  node->total_weight = NodeWeight(node)
    + Weight(node->left)
    + Weight(node->right);

  if (node->left)  node->left ->parent = node;
  if (node->right) node->right->parent = node;

  return node;
}

Node *Merge(Node *lhs, Node *rhs) {
  if (!lhs || !rhs) return lhs ? lhs : rhs;

  if (lhs->priority < rhs->priority) {
    lhs->right = Merge(lhs->right, rhs);
    return Update(lhs);
  } else {
    rhs->left = Merge(lhs, rhs->left);
    return Update(rhs);
  }
}

i64 Take(Node *node, i64 limit) {
  if (limit < Weight(node)) {
    auto right = Weight(node->right);
    auto right_full = right + NodeWeight(node);

    if (limit < right) {
      return Take(node->right, limit);
    } if (limit < right_full) {
      i64 count = (limit - right.value) / node->diamond->weight;
      return static_cast<i64>(Cost(node->right) + 1_l * count * node->diamond->cost);
    } else {
      return static_cast<i64>(NodeCost(node)
                              + Cost(node->right)
                              + Take(node->left, limit - right_full.value));
    }
  } else {
    return static_cast<i64>(Cost(node));
  }
}

void UpdateToRoot(Node *node) {
  for (; node; node = node->parent) {
    Update(node);
  }
}

void Draw(Node *node, Str pref = "", Str step = "\t") {
  if (!node) return;
  cerr << pref << "cost= " << node->total_cost.value << " weight= " << node->total_weight.value << "\n";
  Draw(node->left,  pref + step, step);
  Draw(node->right, pref + step, step);
}

int main() {
  int R(n, q);
  Vec<Diamond> RC(ds, n);

  Vec<int> order(n); iota(A(order), 0); sort(A(order), U(ds[x]));

  Vec<Node> ns(n);
  Node *root = nullptr;
  for (int i : order) {
    ns[i].diamond = &ds[i];
    root = Merge(root, Update(&ns[i]));
  }

  D Draw(root);

  while (q--) {
    int R(t);
    int count, index;

    switch (t) {
      case 1:
        R(count, index);
        ds[--index].count += count;
        UpdateToRoot(&ns[index]);
        break;

      case 2:
        R(count, index);
        ds[--index].count -= count;
        UpdateToRoot(&ns[index]);
        break;

      case 3:
        i64 R(c);
        cout << Take(root, c) << '\n';
        break;
    }
  }
}

namespace {
auto fast_io = [] {
#ifndef DEBUG
#  ifndef INTERACTIVE
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
#  endif // INTERACTIVE
#  ifdef FILES
    freopen(FILES".in", "r", stdin);
    freopen(FILES".out", "w", stdout);
#  endif // FILES
#endif // DEBUG
    cout << setprecision(8) << fixed;
    cerr << boolalpha << setprecision(4) << fixed;

    return 0;
}();
} // namespace
