#include #define endl '\n' //#pragma GCC optimize ("O3") //#pragma GCC target ("sse4") using namespace std; template inline void chkmax(T &x, const T2 &y) { if(x < y) x = y; } template inline void chkmin(T &x, const T2 &y) { if(x > y) x = y; } const int MAXN = (int)1e5 + 42; struct node { int sz, prior, x, y; node *l, *r; node() { x = y = 0; sz = 0; prior = 0; l = nullptr; r = nullptr; } node(int v, int vv) { x = v; y = vv; sz = 1; prior = rand(); l = nullptr; r = nullptr; } }; typedef node* pnode; int size(pnode v) { return v ? v->sz : 0; } void update_size(pnode &v) { if(v) v->sz = size(v->l) + size(v->r) + 1; } void merge(pnode &t, pnode l, pnode r) { if(!l) { t = r; return; } if(!r) { t = l; return; } if(l->prior > r->prior) merge(l->r, l->r, r), t = l; else merge(r->l, l, r->l), t = r; update_size(t); } void split(pnode t, pnode &l, pnode &r, int k) { if(!t) { l = nullptr; r = nullptr; return; } if(t->x <= k) split(t->r, t->r, r, k), l = t; else split(t->l, l, t->l, k), r = t; update_size(t); } void split_y(pnode t, pnode &l, pnode &r, int k) { if(!t) { l = nullptr; r = nullptr; return; } if(t->y >= k) split_y(t->r, t->r, r, k), l = t; else split_y(t->l, l, t->l, k), r = t; update_size(t); } void split_sz(pnode t, pnode &l, pnode &r, int k, int add = 0) { if(!t) { l = nullptr; r = nullptr; return; } int idx = add + size(t->l); if(idx <= k) split_sz(t->r, t->r, r, k, idx + 1), l = t; else split_sz(t->l, l, t->l, k, add), r = t; update_size(t); } int n; int answer[MAXN]; map, int> last; pnode root; list > tr[4 * MAXN]; void add(int ql, int qr, pair pnt, int l, int r, int idx) { if(ql <= l && r <= qr) { tr[idx].push_back(pnt); return; } int mid = (l + r) >> 1; if(ql <= mid) add(ql, qr, pnt, l, mid, 2 * idx + 1); if(mid < qr) add(ql, qr, pnt, mid + 1, r, 2 * idx + 2); } void read() { cin >> n; for(int i = 0; i < n; i++) { int t, x, y; cin >> t >> x >> y; if(t == 1) last[{x, y}] = i; else { add(last[{x, y}], i - 1, {x, y}, 0, n - 1, 0); last[{x, y}] = -1; } } } bool covered(pnode t, pair pnt) { if(!t) return false; if(t->x <= pnt.first && t->y <= pnt.second) return true; if(t->x <= pnt.first) return covered(t->r, pnt); return covered(t->l, pnt); } void rec(int l, int r, int idx) { vector, pnode> > undo_st; for(auto it: tr[idx]) { if(covered(root, it)) continue; pnode l, r, mid = nullptr; split(root, l, r, it.first - 1); split_y(r, mid, r, it.second); pnode nw = new node(it.first, it.second); merge(root, l, nw); merge(root, root, r); undo_st.push_back({it, mid}); } if(l != r) { int mid = (l + r) >> 1; rec(l, mid, 2 * idx + 1); rec(mid + 1, r, 2 * idx + 2); } else answer[l] = size(root); while(!undo_st.empty()) { pair p = undo_st.back().first; pnode to_add = undo_st.back().second; undo_st.pop_back(); pnode l, r, mid; split(root, l, r, p.first - 1); split_y(r, mid, r, p.second); merge(root, l, to_add); merge(root, root, r); } } void solve() { for(auto it: last) if(it.second != -1) add(it.second, n - 1, it.first, 0, n - 1, 0); root = nullptr; rec(0, n - 1, 0); for(int i = 0; i < n; i++) cout << answer[i] << endl; } int main() { freopen("towers.in", "r", stdin); freopen("towers.out", "w", stdout); ios_base::sync_with_stdio(false); cin.tie(NULL); read(); solve(); return 0; }