#include #include #include #include #define rep(i, n) for (int i = 0; i < (n); i++) using namespace std; using namespace __gnu_pbds; using ll = long long; using pii = pair; struct order { ll p, t, a; friend bool operator<(auto a, auto b) { return pii(a.p, a.t) < pii(b.p, b.t); } }; struct md { ll l, r, sum; md(order key) : l(key.p), r(key.p), sum(key.a) {} void operator+=(const md& rhs) { sum += rhs.sum; l = min(l, rhs.l); r = max(r, rhs.r); } }; template struct snu { using metadata_type = md; void operator()(It v, C_it end) { md val(**v); for (auto child : { v.get_l_child(), v.get_r_child() }) if (child != end) val += child.get_metadata(); const_cast(v.get_metadata()) = val; } virtual C_it node_begin() = 0; virtual C_it node_end() = 0; ll query(ll qr) { return query(node_begin(), qr); } ll query(C_it v, ll qr) { if (v == node_end()) return 0; auto [l, r, sum] = v.get_metadata(); auto cmp = Cmp(); if (qr < l) return 0; if (r <= qr) return sum; return ((*v)->p <= qr) * (*v)->a + query(v.get_l_child(), qr) + query(v.get_r_child(), qr); } }; int main() { cin.tie(0)->sync_with_stdio(0); cin.exceptions(cin.failbit); int n; cin >> n; tree, rb_tree_tag, snu> sellers, buyers; ll ans = 0; ostringstream ss; rep(t, n) { string op, type; cin >> op >> type; ll p, a; cin >> p >> a; if (type == "fok") { if (op == "buy" && sellers.query(p) < a) continue; if (op == "sell" && buyers.query(-p) < a) continue; } if (op == "buy") buyers.insert({ -p, t, a }); else if (op == "sell") sellers.insert({ p, t, a }); while (!sellers.empty() && !buyers.empty() && sellers.begin()->p <= -buyers.begin()->p) { auto s = *sellers.begin(); auto b = *buyers.begin(); sellers.erase(sellers.begin()); buyers.erase(buyers.begin()); ll c = min(s.a, b.a); ++ans; ss << s.t + 1 << " " << b.t + 1 << " " << c << "\n"; s.a -= c; b.a -= c; if (s.a) sellers.insert(s); if (b.a) buyers.insert(b); } } cout << ans << "\n"; cout << ss.str(); return 0; }