#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
int read() {
	char ch = getchar(); int x = 0, t = 1;
	while(ch < '0' || ch > '9') { if(ch == '-') t = -1; ch = getchar(); }
	while(ch >= '0' && ch <= '9') x = x*10+ch-'0', ch = getchar();
	return x*t;
}

const int maxn = 3e5+5;
const ll inf = 1e18;
struct Point {
	ll x, y;
	void init() { x = read(), y = read(); }
	ll calc(ll q) { return q*x+y; }
	bool operator <(const Point &b) const {
		return x != b.x ? x < b.x : y < b.y;
	}
	Point operator -(const Point &b) const {
		return (Point){ x-b.x, y-b.y };
	}
	ll operator *(const Point &b) const {
		return x*b.y - y*b.x;
	}
} p[maxn], st[maxn];

int N, tot, top;
int op[maxn], q[maxn], id[maxn], s[maxn], e[maxn];
ll ans[maxn];

struct Segment {
	#define mid (l+r>>1)
	#define lc o<<1, l, mid
	#define rc o<<1|1, mid+1, r
	vector <int> t[maxn<<2];

	void insert(int o, int l, int r, int x) {
		if(s[x] <= l && r <= e[x]) {
			t[o].push_back(x);
			return;
		}
		if(r < s[x] || e[x] < l) return;
		insert(lc, x), insert(rc, x);
	}

	ll query(ll x) {
		int l = 1, r = top;
		if(!top) return -inf;
		while(l < r) {
			int m1 = (2*l+r)/3, m2 = (l+2*r+2)/3;
			if(st[m1].calc(x) < st[m2].calc(x)) l = m1+1;
			else r = m2-1;
		}
		return st[l].calc(x);
	}

	void solve(int o, int l, int r) {
		top = 0;
		sort(t[o].begin(), t[o].end());
		for(int i = 0; i < t[o].size(); ++i) {
			while(top > 1 && (p[t[o][i]]-st[top])*(st[top]-st[top-1]) <= 0)
				--top;
			st[++top] = p[t[o][i]];
		}
		for(int i = l; i <= r; ++i)
			if(op[i] == 3) ans[i] = max(ans[i], query(q[i]));

		if(l == r) return;
		solve(lc), solve(rc);
	}
} T;

int main() {
	N = read();
	for(int i = 1; i <= N; ++i) {
		op[i] = read(), ans[i] = -inf;
		if(op[i] == 1) {
			p[++tot].init();
			s[tot] = i, e[tot] = N;
			id[i] = tot;
		}
		if(op[i] == 2) e[id[read()]] = i-1;
		if(op[i] == 3) q[i] = read();
	}

	for(int i = 1; i <= tot; ++i) T.insert(1, 1, N, i);
	T.solve(1, 1, N);

	for(int i = 1; i <= N; ++i)
	if(op[i] == 3)
		if(ans[i] == -inf) printf("EMPTY SET\n");
		else printf("%lld\n", ans[i]);
	return 0;
}


#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
int read() {
	char ch = getchar(); int x = 0, t = 1;
	while(ch < '0' || ch > '9') { if(ch == '-') t = -1; ch = getchar(); }
	while(ch >= '0' && ch <= '9') x = x*10+ch-'0', ch = getchar();
	return x*t;
}

const int maxn = 3e5+5;
const ll inf = 1e18+5;
struct Point {
	ll x, y;
	void init() { x = read(), y = read(); }
	ll calc(ll q) { return q*x+y; }
	bool operator <(const Point &b) const {
		return x != b.x ? x < b.x : y < b.y;
	}
	Point operator -(const Point &b) const {
		return (Point){ x-b.x, y-b.y };
	}
	ll operator *(const Point &b) const {
		return x*b.y - y*b.x;
	}
} p[maxn], st[maxn];

int N, tot, top;
int op[maxn], q[maxn], id[maxn], s[maxn], e[maxn];
ll ans[maxn];

struct Segment {
	#define mid ((l+r)>>1)
	#define lc o<<1, l, mid
	#define rc o<<1|1, mid+1, r
	vector <Point> t[maxn<<2];

	void insert(int o, int l, int r, int x) {
		if(r < s[x] || e[x] < l) return;
		if(s[x] <= l && r <= e[x]) {
			t[o].push_back(p[x]);
			return;
		}
		insert(lc, x), insert(rc, x);
	}

	ll query(ll x) {
		int l = 1, r = top;
		if(!top) return -inf;
		while(r-l > 6) {
			int m1 = (2*l+r)/3, m2 = (l+2*r)/3;
			if(st[m1].calc(x) < st[m2].calc(x)) l = m1+1;
			else r = m2-1;
		}
		ll ret = -inf;
		for(int i = l; i <= r; ++i)
			ret = max(ret, st[i].calc(x));
		return ret;
	}

	void solve(int o, int l, int r) {
		top = 0;
		sort(t[o].begin(), t[o].end());
		for(int i = 0; i < t[o].size(); ++i) {
			Point x = t[o][i];
			while(top > 1 && (x-st[top])*(st[top]-st[top-1]) <= 0) --top;
			st[++top] = x;
		}
		for(int i = l; i <= r; ++i)
			if(op[i] == 3) ans[i] = max(ans[i], query(q[i]));

		if(l == r) return;
		solve(lc), solve(rc);
	}
} T;

int main() {
	N = read();
	for(int i = 1; i <= N; ++i) {
		op[i] = read(), ans[i] = -inf;
		if(op[i] == 1) {
			p[++tot].init();
			s[tot] = i, e[tot] = N;
			id[i] = tot;
		}
		if(op[i] == 2) e[id[read()]] = i-1;
		if(op[i] == 3) q[i] = read();
	}

	for(int i = 1; i <= tot; ++i) T.insert(1, 1, N, i);
	T.solve(1, 1, N);

	for(int i = 1; i <= N; ++i)
	if(op[i] == 3)
		if(ans[i] == -inf) printf("EMPTY SET\n");
		else printf("%lld\n", ans[i]);
	return 0;
}


#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
int read() {
	char ch = getchar(); int x = 0, t = 1;
	while(ch < '0' || ch > '9') { if(ch == '-') t = -1; ch = getchar(); }
	while(ch >= '0' && ch <= '9') x = x*10+ch-'0', ch = getchar();
	return x*t;
}

const int maxn = 3e5+5;
const ll inf = 2e18;
struct Point {
	ll x, y;
	void init() { x = read(), y = read(); }
	ll calc(ll q) { return q*x+y; }
	bool operator <(const Point &b) const {
		return x != b.x ? x < b.x : y < b.y;
	}
	Point operator -(const Point &b) const {
		return (Point){ x-b.x, y-b.y };
	}
	ll operator *(const Point &b) const {
		return x*b.y - y*b.x;
	}
} p[maxn], st[maxn];

int N, tot, top;
int op[maxn], q[maxn], id[maxn], s[maxn], e[maxn];
ll ans[maxn];

struct Segment {
	#define mid ((l+r)>>1)
	#define lc o<<1, l, mid
	#define rc o<<1|1, mid+1, r
	vector <Point> t[maxn<<2];

	void insert(int o, int l, int r, int x) {
		if(r < s[x] || e[x] < l) return;
		if(s[x] <= l && r <= e[x]) {
			t[o].push_back(p[x]);
			return;
		}
		insert(lc, x), insert(rc, x);
	}

	ll query(ll x) {
		int l = 1, r = top;
		if(!top) return -inf;
		while(r-l > 6) {
			int m1 = (2*l+r)/3, m2 = (l+2*r)/3;
			if(st[m1].calc(x) < st[m2].calc(x)) l = m1+1;
			else r = m2-1;
		}
		ll ret = -inf;
		for(int i = l; i <= r; ++i)
			ret = max(ret, st[i].calc(x));
		return ret;
	}

	void solve(int o, int l, int r) {
		top = 0;
		sort(t[o].begin(), t[o].end());
		for(int i = 0; i < t[o].size(); ++i) {
			Point x = t[o][i];
			while(top > 1 && (x-st[top])*(st[top]-st[top-1]) <= 0) --top;
			st[++top] = x;
		}
		for(int i = l; i <= r; ++i)
			if(op[i] == 3) ans[i] = max(ans[i], query(q[i]));

		if(l == r) return;
		solve(lc), solve(rc);
	}
} T;

int main() {
	N = read();
	for(int i = 1; i <= N; ++i) {
		op[i] = read(), ans[i] = -inf;
		if(op[i] == 1) {
			p[++tot].init();
			s[tot] = i, e[tot] = N;
			id[i] = tot;
		}
		if(op[i] == 2) e[id[read()]] = i-1;
		if(op[i] == 3) q[i] = read();
	}

	for(int i = 1; i <= tot; ++i) T.insert(1, 1, N, i);
	T.solve(1, 1, N);

	for(int i = 1; i <= N; ++i)
	if(op[i] == 3)
		if(ans[i] == -inf) printf("EMPTY SET\n");
		else printf("%lld\n", ans[i]);
	return 0;
}


#include <cstdio>
#include <algorithm>
#include <vector>
using namespace std;
typedef long long ll;
int read() {
	char ch = getchar(); int x = 0, t = 1;
	while(ch < '0' || ch > '9') { if(ch == '-') t = -1; ch = getchar(); }
	while(ch >= '0' && ch <= '9') x = x*10+ch-'0', ch = getchar();
	return x*t;
}

const int maxn = 3e5+5;
const ll inf = 1e18;
struct Point {
	ll x, y;
	void init() { x = read(), y = read(); }
	ll calc(ll q) { return q*x+y; }
	bool operator <(const Point &b) const {
		return x != b.x ? x < b.x : y < b.y;
	}
	Point operator -(const Point &b) const {
		return (Point){ x-b.x, y-b.y };
	}
	ll operator *(const Point &b) const {
		return x*b.y - y*b.x;
	}
} p[maxn], st[maxn];

int N, tot, top;
int op[maxn], q[maxn], id[maxn], s[maxn], e[maxn];
ll ans[maxn];

struct Segment {
	#define mid ((l+r)>>1)
	#define lc o<<1, l, mid
	#define rc o<<1|1, mid+1, r
	vector <Point> t[maxn<<2];

	void insert(int o, int l, int r, int x) {
		if(r < s[x] || e[x] < l) return;
		if(s[x] <= l && r <= e[x]) {
			t[o].push_back(p[x]);
			return;
		}
		insert(lc, x), insert(rc, x);
	}

	ll query(ll x) {
		int l = 1, r = top;
		if(!top) return -inf;
		while(r-l > 6) {
			int m1 = (2*l+r)/3, m2 = (l+2*r)/3;
			if(st[m1].calc(x) < st[m2].calc(x)) l = m1+1;
			else r = m2-1;
		}
		ll ret = -inf;
		for(int i = l; i <= r; ++i)
			ret = max(ret, st[i].calc(x));
		return ret;
	}

	void solve(int o, int l, int r) {
		top = 0;
		sort(t[o].begin(), t[o].end());
		for(int i = 0; i < t[o].size(); ++i) {
			Point x = t[o][i];
			while(top > 1 && (x-st[top])*(st[top]-st[top-1]) <= 0) --top;
			st[++top] = x;
		}
		for(int i = l; i <= r; ++i)
			if(op[i] == 3) ans[i] = max(ans[i], query(q[i]));

		if(l == r) return;
		solve(lc), solve(rc);
	}
} T;

int main() {
	N = read();
	for(int i = 1; i <= N; ++i) {
		op[i] = read(), ans[i] = -inf;
		if(op[i] == 1) {
			p[++tot].init();
			s[tot] = i, e[tot] = N;
			id[i] = tot;
		}
		if(op[i] == 2) e[id[read()]] = i-1;
		if(op[i] == 3) q[i] = read();
	}

	for(int i = 1; i <= tot; ++i) T.insert(1, 1, N, i);
	T.solve(1, 1, N);

	for(int i = 1; i <= N; ++i)
	if(op[i] == 3)
		if(ans[i] == -inf) printf("EMPTY SET\n");
		else printf("%lld\n", ans[i]);
	return 0;
}


/*input
7
3 1
1 2 3
3 1
1 -1 100
3 1
2 4
3 1

*/
#include <bits/stdc++.h>
using namespace std;
#define sp ' '
#define endl '\n'
#define fi first
#define se second
#define mp make_pair
#define __builtin_popcount __builtin_popcountll
#define int long long
#define bit(x,y) ((x>>y)&1LL)
#define loop(i,l,r) for(int i=(int)l; i<=(int)r; i++)
#define rloop(i,l,r) for(int i=(int)l; i>=(int)r; i--)
#ifdef UncleGrandpa
const int N = 305;
#else
const int N = 300005;
#endif

void read(int &number) {
    bool negative = false;
    int c;
    number = 0;
    c = getchar();
    while (c == ' ' || c == '\n')
        c = getchar();
    if (c == '-') {
        negative = true;
        c = getchar();
    }
    for (; (c > 47 && c < 58); c = getchar())
        number = number * 10 + c - 48;
    if (negative)
        number = -number;
}

template <class T1, class T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &a) {
    return os << '(' << a.first << ", " << a.second << ')';
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &a) {
    os << '[';
    for (unsigned int i = 0; i < a.size(); i++)
        os << a[i] << (i < a.size() - 1 ? ", " : "");
    os << ']';
    return os;
}
template <class T>
ostream &operator<<(ostream &os, const set<T> &a) {
    os << '{';
    for (typename set<T>::iterator it = a.begin(); it != a.end(); it++) {
        typename set<T>::iterator jt = it;
        os << *it << (++jt != a.end() ? ", " : "");
    }
    os << '}';
    return os;
}
template <class T1, class T2>
ostream &operator<<(ostream &os, map<T1, T2> &a) {
    os << "{\n";
    for (typename map<T1, T2>::iterator it = a.begin(); it != a.end(); it++) {
        typename map<T1, T2>::iterator jt = it;
        os << "  " << it->first << ": " << it->second << (++jt != a.end() ? ",\n" : "\n");
    }
    os << '}';
    return os;
}
struct Line {
    int A, B;
    int sta, en;
    Line(int _A, int _B, int _sta, int _en): A(_A), B(_B), sta(_sta), en(_en) {};
    Line() {};
};

const int INF = 4e18;
struct ConvexHullTrick {
    vector<int> A, B;
    bool increasing_slope, need_tenary;
    bool bad(int l1, int l2, int l3) {
        if (increasing_slope)
            return (B[l3] - B[l1]) * (A[l1] - A[l2]) < (A[l1] - A[l3]) * (B[l2] - B[l1]);
        return (B[l3] - B[l1]) * (A[l1] - A[l2]) > (A[l1] - A[l3]) * (B[l2] - B[l1]);
    }
    void init(bool _increasing_slope, bool _need_tenary) {
        increasing_slope = _increasing_slope; need_tenary = _need_tenary;
        A.clear(); B.clear();
    }
    void add(int x, int y) {
        if (!A.empty()) {
            if (A.back() == x && B.back() <= y) A.pop_back(), B.pop_back();
        }
        A.push_back(x);
        B.push_back(y);
        while (A.size() > 2 && bad(A.size() - 3, A.size() - 2, A.size() - 1)) {
            A.erase(A.end() - 2);
            B.erase(B.end() - 2);
        }
    }
    int curit = 0;
    int query(int x) {
        assert(!A.empty());
        if (!need_tenary) {
            curit = min(curit, (int)A.size() - 1);
            while (curit != A.size() - 1 && A[curit] * 1LL * x + B[curit] <= A[curit + 1] * 1LL * x + B[curit + 1]) curit++;
            return A[curit] * 1LL * x + B[curit];
        }
        int l = 0, r = (int)(A.size()) - 1;
        while (r - l > 2) {
            int mid1 = (l * 2 + r) / 3; int mid2 = (l + 2 * r) / 3;
            int val1 = A[mid1] * x + B[mid1]; int val2 = A[mid2] * x + B[mid2];
            if (val1 == val2)
                l = mid1, r = mid2;
            else if (val1 < val2)l = mid1;
            else r = mid2;
        }
        int ret = -INF;
        for (int i = l; i <= r; i++)
            ret = max(ret, A[i] * x + B[i]);
        return ret;
    }
} CV;

ConvexHullTrick f[4 * N];
void init(int k, int l, int r) {
    f[k].init(1, 0);
    if (l == r) return;
    int mid = (l + r) / 2;
    init(k * 2, l, mid); init(k * 2 + 1, mid + 1, r);
}

void update(int k, int l, int r, const int L, const int R, const Line X) {
    if (r < L || R < l) return;
    if (L <= l && r <= R) {
        f[k].add(X.A, X.B);
        return;
    }
    int mid = (l + r) / 2;
    update(k * 2, l, mid, L, R, X); update(k * 2 + 1, mid + 1, r, L, R, X);
}

int get(int k, int l, int r, int pos, int X) {
    if (r < pos || pos < l) return -INF;
    int ret = -INF;
    if (!f[k].A.empty()) ret = f[k].query(X);
    if (l == r) return ret;
    int mid = (l + r) / 2;
    ret = max(ret, get(k * 2, l, mid, pos, X));
    ret = max(ret, get(k * 2 + 1, mid + 1, r, pos, X));
    return ret;
}

struct Query {
    int time, X, ans;
};

signed main() {
#ifndef UncleGrandpa
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#endif
    vector<Line> line; vector<int> where(N);
    vector<Query> query;// pair Time, X
    int q;
    cin >> q;
    loop(Q, 1, q) {
        int type; cin >> type;
        if (type == 1) {
            Line X;
            cin >> X.A >> X.B; X.sta = Q; X.en = q;
            line.push_back(X); where[Q] = line.size() - 1;
        }
        else if (type == 2) {
            int t; cin >> t;
            line[where[t]].en = Q;
        }
        else if (type == 3) {
            int x; cin >> x;
            query.push_back(Query{Q, x, 0});
        }
    }
    sort(line.begin(), line.end(), [&](Line X, Line Y) {
        return X.A < Y.A;
    });
    sort(query.begin(), query.end(), [&](Query X, Query Y) {
        return X.X < Y.X;
    });
    init(1, 1, q);
    for (auto it : line) {
        update(1, 1, q, it.sta, it.en, it);
    }
    for (auto &it : query)
        it.ans = get(1, 1, q, it.time, it.X);
    sort(query.begin(), query.end(), [&](Query X, Query Y) {
        return X.time < Y.time;
    });
    for (auto &it : query) {
        if (it.ans == -INF) cout << "EMPTY SET" << endl;
        else cout << it.ans << endl;
    }
}


/*input
7
3 1
1 2 3
3 1
1 -1 100
3 1
2 4
3 1

*/
#include <bits/stdc++.h>
using namespace std;
#define sp ' '
#define endl '\n'
#define fi first
#define se second
#define mp make_pair
#define __builtin_popcount __builtin_popcountll
#define int long long
#define bit(x,y) ((x>>y)&1LL)
#define loop(i,l,r) for(int i=(int)l; i<=(int)r; i++)
#define rloop(i,l,r) for(int i=(int)l; i>=(int)r; i--)
const int N = 300005;

void read(int &number) {
    bool negative = false;
    int c;
    number = 0;
    c = getchar();
    while (c == ' ' || c == '\n')
        c = getchar();
    if (c == '-') {
        negative = true;
        c = getchar();
    }
    for (; (c > 47 && c < 58); c = getchar())
        number = number * 10 + c - 48;
    if (negative)
        number = -number;
}

template <class T1, class T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &a) {
    return os << '(' << a.first << ", " << a.second << ')';
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &a) {
    os << '[';
    for (unsigned int i = 0; i < a.size(); i++)
        os << a[i] << (i < a.size() - 1 ? ", " : "");
    os << ']';
    return os;
}
template <class T>
ostream &operator<<(ostream &os, const set<T> &a) {
    os << '{';
    for (typename set<T>::iterator it = a.begin(); it != a.end(); it++) {
        typename set<T>::iterator jt = it;
        os << *it << (++jt != a.end() ? ", " : "");
    }
    os << '}';
    return os;
}
template <class T1, class T2>
ostream &operator<<(ostream &os, map<T1, T2> &a) {
    os << "{\n";
    for (typename map<T1, T2>::iterator it = a.begin(); it != a.end(); it++) {
        typename map<T1, T2>::iterator jt = it;
        os << "  " << it->first << ": " << it->second << (++jt != a.end() ? ",\n" : "\n");
    }
    os << '}';
    return os;
}
struct Line {
    int A, B;
    int sta, en;
    Line(int _A, int _B, int _sta, int _en): A(_A), B(_B), sta(_sta), en(_en) {};
    Line() {};
};

const int INF = 1e18;
struct ConvexHullTrick {
    vector<int> A, B;
    bool increasing_slope, need_tenary;
    bool bad(int l1, int l2, int l3) {
        if (increasing_slope)
            return (B[l3] - B[l1]) * (A[l1] - A[l2]) < (A[l1] - A[l3]) * (B[l2] - B[l1]);
        return (B[l3] - B[l1]) * (A[l1] - A[l2]) > (A[l1] - A[l3]) * (B[l2] - B[l1]);
    }
    void init(bool _increasing_slope, bool _need_tenary) {
        increasing_slope = _increasing_slope; need_tenary = _need_tenary;
        A.clear(); B.clear();
    }
    void add(int x, int y) {
        if (!A.empty()) {
            if (A.back() == x && B.back() >= y) A.pop_back(), B.pop_back();
        }
        A.push_back(x);
        B.push_back(y);
        while (A.size() > 2 && bad(A.size() - 3, A.size() - 2, A.size() - 1)) {
            A.erase(A.end() - 2);
            B.erase(B.end() - 2);
        }
    }
    int curit = 0;
    int query(int x) {
        if (A.empty()) assert(false);
        curit = min(curit, (int)A.size() - 1); curit = max(curit, 0LL);
        while (curit != A.size() - 1 && A[curit] * 1LL * x + B[curit] >= A[curit + 1] * 1LL * x + B[curit + 1]) curit++;
        return A[curit] * 1LL * x + B[curit];
    }
};

ConvexHullTrick f[4 * N];
void init(int k, int l, int r) {
    f[k].init(1, 0);
    if (l == r) return;
    int mid = (l + r) / 2;
    init(k * 2, l, mid); init(k * 2 + 1, mid + 1, r);
}

void update(int k, int l, int r, const int L, const int R, const Line X) {
    if (r < L || R < l) return;
    if (L <= l && r <= R) {
        f[k].add(X.A, X.B);
        return;
    }
    int mid = (l + r) / 2;
    update(k * 2, l, mid, L, R, X); update(k * 2 + 1, mid + 1, r, L, R, X);
}

int get(int k, int l, int r, int pos, int X) {
    if (r < pos || pos < l) return -INF;
    int ret = -INF;
    if (!f[k].A.empty()) ret = f[k].query(X);
    if (l == r) return ret;
    int mid = (l + r) / 2;
    ret = max(ret, get(k * 2, l, mid, pos, X));
    ret = max(ret, get(k * 2 + 1, mid + 1, r, pos, X));
    return ret;
}

signed main() {
#ifndef UncleGrandpa
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#endif
    vector<Line> line; vector<int> where(N);
    vector<pair<int, int> > query;// pair Time, X
    int q;
    cin >> q;
    loop(Q, 1, q) {
        int type; cin >> type;
        if (type == 1) {
            Line X;
            cin >> X.A >> X.B; X.sta = Q; X.en = q;
            line.push_back(X); where[Q] = line.size() - 1;
        }
        else if (type == 2) {
            int t; cin >> t;
            line[where[t]].en = Q;
        }
        else if (type == 3) {
            int x; cin >> x;
            query.push_back(mp(Q, x));
        }
    }
    sort(line.begin(), line.end(), [&](Line X, Line Y) {
        return X.A < Y.A;
    });
    init(1, 1, q);
    for (auto it : line) {
        update(1, 1, q, it.sta, it.en, it);
    }
    for (auto it : query) {
        int rec = get(1, 1, q, it.fi, it.se);
        if (rec == -INF) cout << "EMPTY SET" << endl;
        else cout << rec << endl;
    }
}


/*input
7
3 1
1 2 3
3 1
1 -1 100
3 1
2 4
3 1

*/
#include <bits/stdc++.h>
using namespace std;
#define sp ' '
#define endl '\n'
#define fi first
#define se second
#define mp make_pair
#define __builtin_popcount __builtin_popcountll
#define int long long
#define bit(x,y) ((x>>y)&1LL)
#define loop(i,l,r) for(int i=(int)l; i<=(int)r; i++)
#define rloop(i,l,r) for(int i=(int)l; i>=(int)r; i--)
const int N = 300005;

void read(int &number) {
    bool negative = false;
    int c;
    number = 0;
    c = getchar();
    while (c == ' ' || c == '\n')
        c = getchar();
    if (c == '-') {
        negative = true;
        c = getchar();
    }
    for (; (c > 47 && c < 58); c = getchar())
        number = number * 10 + c - 48;
    if (negative)
        number = -number;
}

template <class T1, class T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &a) {
    return os << '(' << a.first << ", " << a.second << ')';
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &a) {
    os << '[';
    for (unsigned int i = 0; i < a.size(); i++)
        os << a[i] << (i < a.size() - 1 ? ", " : "");
    os << ']';
    return os;
}
template <class T>
ostream &operator<<(ostream &os, const set<T> &a) {
    os << '{';
    for (typename set<T>::iterator it = a.begin(); it != a.end(); it++) {
        typename set<T>::iterator jt = it;
        os << *it << (++jt != a.end() ? ", " : "");
    }
    os << '}';
    return os;
}
template <class T1, class T2>
ostream &operator<<(ostream &os, map<T1, T2> &a) {
    os << "{\n";
    for (typename map<T1, T2>::iterator it = a.begin(); it != a.end(); it++) {
        typename map<T1, T2>::iterator jt = it;
        os << "  " << it->first << ": " << it->second << (++jt != a.end() ? ",\n" : "\n");
    }
    os << '}';
    return os;
}
struct Line {
    int A, B;
    int sta, en;
    Line(int _A, int _B, int _sta, int _en): A(_A), B(_B), sta(_sta), en(_en) {};
    Line() {};
};

const int INF = 1e18;
struct ConvexHullTrick {
    vector<int> A, B;
    bool increasing_slope, need_tenary;
    bool bad(int l1, int l2, int l3) {
        if (increasing_slope)
            return (B[l3] - B[l1]) * (A[l1] - A[l2]) < (A[l1] - A[l3]) * (B[l2] - B[l1]);
        return (B[l3] - B[l1]) * (A[l1] - A[l2]) > (A[l1] - A[l3]) * (B[l2] - B[l1]);
    }
    void init(bool _increasing_slope, bool _need_tenary) {
        increasing_slope = _increasing_slope; need_tenary = _need_tenary;
        A.clear(); B.clear();
    }
    void add(int x, int y) {
        if (!A.empty()) {
            if (A.back() == x && B.back() <= y) A.pop_back(), B.pop_back();
        }
        A.push_back(x);
        B.push_back(y);
        while (A.size() > 2 && bad(A.size() - 3, A.size() - 2, A.size() - 1)) {
            A.erase(A.end() - 2);
            B.erase(B.end() - 2);
        }
    }
    int curit = 0;
    int query(int x) {
        assert(!A.empty());
        if (!need_tenary) {
            curit = min(curit, (int)A.size() - 1);
            while (curit != A.size() - 1 && A[curit] * 1LL * x + B[curit] <= A[curit + 1] * 1LL * x + B[curit + 1]) curit++;
            return A[curit] * 1LL * x + B[curit];
        }
        int l = 0, r = (int)(A.size()) - 1;
        while (r - l > 2) {
            int mid1 = (l * 2 + r) / 3; int mid2 = (l + 2 * r) / 3;
            int val1 = A[mid1] * x + B[mid1]; int val2 = A[mid2] * x + B[mid2];
            if (val1 == val2)
                l = mid1, r = mid2;
            else if (val1 < val2)l = mid1;
            else r = mid2;
        }
        int ret = -1e18;
        for (int i = l; i <= r; i++)
            ret = max(ret, A[i] * x + B[i]);
        return ret;
    }
} CV;

ConvexHullTrick f[4 * N];
void init(int k, int l, int r) {
    f[k].init(1, 1);
    if (l == r) return;
    int mid = (l + r) / 2;
    init(k * 2, l, mid); init(k * 2 + 1, mid + 1, r);
}

void update(int k, int l, int r, const int L, const int R, const Line X) {
    if (r < L || R < l) return;
    if (L <= l && r <= R) {
        f[k].add(X.A, X.B);
        return;
    }
    int mid = (l + r) / 2;
    update(k * 2, l, mid, L, R, X); update(k * 2 + 1, mid + 1, r, L, R, X);
}

int get(int k, int l, int r, int pos, int X) {
    if (r < pos || pos < l) return -INF;
    int ret = -INF;
    if (!f[k].A.empty()) ret = f[k].query(X);
    if (l == r) return ret;
    int mid = (l + r) / 2;
    ret = max(ret, get(k * 2, l, mid, pos, X));
    ret = max(ret, get(k * 2 + 1, mid + 1, r, pos, X));
    return ret;
}

signed main() {
#ifndef UncleGrandpa
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#endif
    vector<Line> line; vector<int> where(N);
    vector<pair<int, int> > query;// pair Time, X
    int q;
    cin >> q;
    loop(Q, 1, q) {
        int type; cin >> type;
        if (type == 1) {
            Line X;
            cin >> X.A >> X.B; X.sta = Q; X.en = q;
            line.push_back(X); where[Q] = line.size() - 1;
        }
        else if (type == 2) {
            int t; cin >> t;
            line[where[t]].en = Q;
        }
        else if (type == 3) {
            int x; cin >> x;
            query.push_back(mp(Q, x));
        }
    }
    sort(line.begin(), line.end(), [&](Line X, Line Y) {
        return X.A < Y.A;
    });
    init(1, 1, q);
    for (auto it : line) {
        update(1, 1, q, it.sta, it.en, it);
    }
    for (auto it : query) {
        int rec = get(1, 1, q, it.fi, it.se);
        if (rec == -INF) cout << "EMPTY SET" << endl;
        else cout << rec << endl;
    }
}


/*input
7
3 1
1 2 3
3 1
1 -1 100
3 1
2 4
3 1

*/
#include <bits/stdc++.h>
using namespace std;
#define sp ' '
#define endl '\n'
#define fi first
#define se second
#define mp make_pair
#define __builtin_popcount __builtin_popcountll
#define int long long
#define bit(x,y) ((x>>y)&1LL)
#define loop(i,l,r) for(int i=(int)l; i<=(int)r; i++)
#define rloop(i,l,r) for(int i=(int)l; i>=(int)r; i--)
const int N = 300005;

void read(int &number) {
    bool negative = false;
    int c;
    number = 0;
    c = getchar();
    while (c == ' ' || c == '\n')
        c = getchar();
    if (c == '-') {
        negative = true;
        c = getchar();
    }
    for (; (c > 47 && c < 58); c = getchar())
        number = number * 10 + c - 48;
    if (negative)
        number = -number;
}

template <class T1, class T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &a) {
    return os << '(' << a.first << ", " << a.second << ')';
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &a) {
    os << '[';
    for (unsigned int i = 0; i < a.size(); i++)
        os << a[i] << (i < a.size() - 1 ? ", " : "");
    os << ']';
    return os;
}
template <class T>
ostream &operator<<(ostream &os, const set<T> &a) {
    os << '{';
    for (typename set<T>::iterator it = a.begin(); it != a.end(); it++) {
        typename set<T>::iterator jt = it;
        os << *it << (++jt != a.end() ? ", " : "");
    }
    os << '}';
    return os;
}
template <class T1, class T2>
ostream &operator<<(ostream &os, map<T1, T2> &a) {
    os << "{\n";
    for (typename map<T1, T2>::iterator it = a.begin(); it != a.end(); it++) {
        typename map<T1, T2>::iterator jt = it;
        os << "  " << it->first << ": " << it->second << (++jt != a.end() ? ",\n" : "\n");
    }
    os << '}';
    return os;
}
struct Line {
    int A, B;
    int sta, en;
    Line(int _A, int _B, int _sta, int _en): A(_A), B(_B), sta(_sta), en(_en) {};
    Line() {};
};

const int INF = 4e18;
struct ConvexHullTrick {
    vector<int> A, B;
    bool increasing_slope, need_tenary;
    bool bad(int l1, int l2, int l3) {
        if (increasing_slope)
            return (B[l3] - B[l1]) * (A[l1] - A[l2]) < (A[l1] - A[l3]) * (B[l2] - B[l1]);
        return (B[l3] - B[l1]) * (A[l1] - A[l2]) > (A[l1] - A[l3]) * (B[l2] - B[l1]);
    }
    void init(bool _increasing_slope, bool _need_tenary) {
        increasing_slope = _increasing_slope; need_tenary = _need_tenary;
        A.clear(); B.clear();
    }
    void add(int x, int y) {
        if (!A.empty()) {
            if (A.back() == x && B.back() <= y) A.pop_back(), B.pop_back();
        }
        A.push_back(x);
        B.push_back(y);
        while (A.size() > 2 && bad(A.size() - 3, A.size() - 2, A.size() - 1)) {
            A.erase(A.end() - 2);
            B.erase(B.end() - 2);
        }
    }
    int curit = 0;
    int query(int x) {
        assert(!A.empty());
        if (!need_tenary) {
            curit = min(curit, (int)A.size() - 1);
            while (curit != A.size() - 1 && A[curit] * 1LL * x + B[curit] <= A[curit + 1] * 1LL * x + B[curit + 1]) curit++;
            return A[curit] * 1LL * x + B[curit];
        }
        int l = 0, r = (int)(A.size()) - 1;
        while (r - l > 2) {
            int mid1 = (l * 2 + r) / 3; int mid2 = (l + 2 * r) / 3;
            int val1 = A[mid1] * x + B[mid1]; int val2 = A[mid2] * x + B[mid2];
            if (val1 == val2)
                l = mid1, r = mid2;
            else if (val1 < val2)l = mid1;
            else r = mid2;
        }
        int ret = -INF;
        for (int i = l; i <= r; i++)
            ret = max(ret, A[i] * x + B[i]);
        return ret;
    }
} CV;

ConvexHullTrick f[4 * N];
void init(int k, int l, int r) {
    f[k].init(1, 1);
    if (l == r) return;
    int mid = (l + r) / 2;
    init(k * 2, l, mid); init(k * 2 + 1, mid + 1, r);
}

void update(int k, int l, int r, const int L, const int R, const Line X) {
    if (r < L || R < l) return;
    if (L <= l && r <= R) {
        f[k].add(X.A, X.B);
        return;
    }
    int mid = (l + r) / 2;
    update(k * 2, l, mid, L, R, X); update(k * 2 + 1, mid + 1, r, L, R, X);
}

int get(int k, int l, int r, int pos, int X) {
    if (r < pos || pos < l) return -INF;
    int ret = -INF;
    if (!f[k].A.empty()) ret = f[k].query(X);
    if (l == r) return ret;
    int mid = (l + r) / 2;
    ret = max(ret, get(k * 2, l, mid, pos, X));
    ret = max(ret, get(k * 2 + 1, mid + 1, r, pos, X));
    return ret;
}

signed main() {
#ifndef UncleGrandpa
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#endif
    vector<Line> line; vector<int> where(N);
    vector<pair<int, int> > query;// pair Time, X
    int q;
    cin >> q;
    loop(Q, 1, q) {
        int type; cin >> type;
        if (type == 1) {
            Line X;
            cin >> X.A >> X.B; X.sta = Q; X.en = q;
            line.push_back(X); where[Q] = line.size() - 1;
        }
        else if (type == 2) {
            int t; cin >> t;
            line[where[t]].en = Q;
        }
        else if (type == 3) {
            int x; cin >> x;
            query.push_back(mp(Q, x));
        }
    }
    sort(line.begin(), line.end(), [&](Line X, Line Y) {
        return X.A < Y.A;
    });
    init(1, 1, q);
    for (auto it : line) {
        update(1, 1, q, it.sta, it.en, it);
    }
    for (auto it : query) {
        int rec = get(1, 1, q, it.fi, it.se);
        if (rec == -INF) cout << "EMPTY SET" << endl;
        else cout << rec << endl;
    }
}


/*input
7
3 1
1 2 3
3 1
1 -1 100
3 1
2 4
3 1

*/
#include <bits/stdc++.h>
using namespace std;
#define sp ' '
#define endl '\n'
#define fi first
#define se second
#define mp make_pair
#define __builtin_popcount __builtin_popcountll
#define int long long
#define bit(x,y) ((x>>y)&1LL)
#define loop(i,l,r) for(int i=(int)l; i<=(int)r; i++)
#define rloop(i,l,r) for(int i=(int)l; i>=(int)r; i--)
const int N = 35;

void read(int &number) {
    bool negative = false;
    int c;
    number = 0;
    c = getchar();
    while (c == ' ' || c == '\n')
        c = getchar();
    if (c == '-') {
        negative = true;
        c = getchar();
    }
    for (; (c > 47 && c < 58); c = getchar())
        number = number * 10 + c - 48;
    if (negative)
        number = -number;
}

template <class T1, class T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &a) {
    return os << '(' << a.first << ", " << a.second << ')';
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &a) {
    os << '[';
    for (unsigned int i = 0; i < a.size(); i++)
        os << a[i] << (i < a.size() - 1 ? ", " : "");
    os << ']';
    return os;
}
template <class T>
ostream &operator<<(ostream &os, const set<T> &a) {
    os << '{';
    for (typename set<T>::iterator it = a.begin(); it != a.end(); it++) {
        typename set<T>::iterator jt = it;
        os << *it << (++jt != a.end() ? ", " : "");
    }
    os << '}';
    return os;
}
template <class T1, class T2>
ostream &operator<<(ostream &os, map<T1, T2> &a) {
    os << "{\n";
    for (typename map<T1, T2>::iterator it = a.begin(); it != a.end(); it++) {
        typename map<T1, T2>::iterator jt = it;
        os << "  " << it->first << ": " << it->second << (++jt != a.end() ? ",\n" : "\n");
    }
    os << '}';
    return os;
}
struct Line {
    int A, B;
    int sta, en;
    Line(int _A, int _B, int _sta, int _en): A(_A), B(_B), sta(_sta), en(_en) {};
    Line() {};
};

const int INF = 1e18;
struct ConvexHullTrick {
    vector<int> A, B;
    bool increasing_slope, need_tenary;
    bool bad(int l1, int l2, int l3) {
        if (increasing_slope)
            return (B[l3] - B[l1]) * (A[l1] - A[l2]) < (A[l1] - A[l3]) * (B[l2] - B[l1]);
        return (B[l3] - B[l1]) * (A[l1] - A[l2]) > (A[l1] - A[l3]) * (B[l2] - B[l1]);
    }
    void init(bool _increasing_slope, bool _need_tenary) {
        increasing_slope = _increasing_slope; need_tenary = _need_tenary;
        A.clear(); B.clear();
    }
    void add(int x, int y) {
        if (!A.empty()) {
            if (A.back() == x && B.back() >= y) A.pop_back(), B.pop_back();
        }
        A.push_back(x);
        B.push_back(y);
        while (A.size() > 2 && bad(A.size() - 3, A.size() - 2, A.size() - 1)) {
            A.erase(A.end() - 2);
            B.erase(B.end() - 2);
        }
    }
    int curit = 0;
    int query(int x) {
        curit = min(curit, (int)A.size() - 1);
        while (curit != A.size() - 1 && A[curit] * 1LL * x + B[curit] >= A[curit + 1] * 1LL * x + B[curit + 1]) curit++;
        return A[curit] * 1LL * x + B[curit];
    }
};

ConvexHullTrick f[4 * N];
void init(int k, int l, int r) {
    f[k].init(1, 0);
    if (l == r) return;
    int mid = (l + r) / 2;
    init(k * 2, l, mid); init(k * 2 + 1, mid + 1, r);
}

void update(int k, int l, int r, const int L, const int R, const Line X) {
    if (r < L || R < l) return;
    if (L <= l && r <= R) {
        f[k].add(X.A, X.B);
        return;
    }
    int mid = (l + r) / 2;
    update(k * 2, l, mid, L, R, X); update(k * 2 + 1, mid + 1, r, L, R, X);
}

int get(int k, int l, int r, int pos, int X) {
    if (r < pos || pos < l) return -INF;
    int ret = -INF;
    if (!f[k].A.empty()) ret = f[k].query(X);
    if (l == r) return ret;
    int mid = (l + r) / 2;
    ret = max(ret, get(k * 2, l, mid, pos, X));
    ret = max(ret, get(k * 2 + 1, mid + 1, r, pos, X));
    return ret;
}

signed main() {
#ifndef UncleGrandpa
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#endif
    vector<Line> line; vector<int> where(N);
    vector<pair<int, int> > query;// pair Time, X
    int q;
    cin >> q;
    loop(Q, 1, q) {
        int type; cin >> type;
        if (type == 1) {
            Line X;
            cin >> X.A >> X.B; X.sta = Q; X.en = q;
            line.push_back(X); where[Q] = line.size() - 1;
        }
        else if (type == 2) {
            int t; cin >> t;
            line[where[t]].en = Q;
        }
        else if (type == 3) {
            int x; cin >> x;
            query.push_back(mp(Q, x));
        }
    }
    sort(line.begin(), line.end(), [&](Line X, Line Y) {
        return X.A < Y.A;
    });
    init(1, 1, q);
    for (auto it : line) {
        update(1, 1, q, it.sta, it.en, it);
    }
    for (auto it : query) {
        int rec = get(1, 1, q, it.fi, it.se);
        if (rec == -INF) cout << "EMPTY SET" << endl;
        else cout << rec << endl;
    }
}


/*input
7
3 1
1 2 3
3 1
1 -1 100
3 1
2 4
3 1

*/
#include <bits/stdc++.h>
using namespace std;
#define sp ' '
#define endl '\n'
#define fi first
#define se second
#define mp make_pair
#define __builtin_popcount __builtin_popcountll
#define int long long
#define bit(x,y) ((x>>y)&1LL)
#define loop(i,l,r) for(int i=(int)l; i<=(int)r; i++)
#define rloop(i,l,r) for(int i=(int)l; i>=(int)r; i--)
const int N = 35;

void read(int &number) {
    bool negative = false;
    int c;
    number = 0;
    c = getchar();
    while (c == ' ' || c == '\n')
        c = getchar();
    if (c == '-') {
        negative = true;
        c = getchar();
    }
    for (; (c > 47 && c < 58); c = getchar())
        number = number * 10 + c - 48;
    if (negative)
        number = -number;
}

template <class T1, class T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &a) {
    return os << '(' << a.first << ", " << a.second << ')';
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &a) {
    os << '[';
    for (unsigned int i = 0; i < a.size(); i++)
        os << a[i] << (i < a.size() - 1 ? ", " : "");
    os << ']';
    return os;
}
template <class T>
ostream &operator<<(ostream &os, const set<T> &a) {
    os << '{';
    for (typename set<T>::iterator it = a.begin(); it != a.end(); it++) {
        typename set<T>::iterator jt = it;
        os << *it << (++jt != a.end() ? ", " : "");
    }
    os << '}';
    return os;
}
template <class T1, class T2>
ostream &operator<<(ostream &os, map<T1, T2> &a) {
    os << "{\n";
    for (typename map<T1, T2>::iterator it = a.begin(); it != a.end(); it++) {
        typename map<T1, T2>::iterator jt = it;
        os << "  " << it->first << ": " << it->second << (++jt != a.end() ? ",\n" : "\n");
    }
    os << '}';
    return os;
}
struct Line {
    int A, B;
    int sta, en;
    Line(int _A, int _B, int _sta, int _en): A(_A), B(_B), sta(_sta), en(_en) {};
    Line() {};
};

const int INF = 1e18;
struct ConvexHullTrick {
    vector<int> A, B;
    bool increasing_slope, need_tenary;
    bool bad(int l1, int l2, int l3) {
        if (increasing_slope)
            return (B[l3] - B[l1]) * (A[l1] - A[l2]) < (A[l1] - A[l3]) * (B[l2] - B[l1]);
        return (B[l3] - B[l1]) * (A[l1] - A[l2]) > (A[l1] - A[l3]) * (B[l2] - B[l1]);
    }
    void init(bool _increasing_slope, bool _need_tenary) {
        increasing_slope = _increasing_slope; need_tenary = _need_tenary;
        A.clear(); B.clear();
    }
    void add(int x, int y) {
        if (!A.empty()) {
            if (A.back() == x && B.back() >= y) A.pop_back(), B.pop_back();
        }
        A.push_back(x);
        B.push_back(y);
        while (A.size() > 2 && bad(A.size() - 3, A.size() - 2, A.size() - 1)) {
            A.erase(A.end() - 2);
            B.erase(B.end() - 2);
        }
    }
    int curit = 0;
    int query(int x) {
        if (A.empty()) assert(false);
        curit = min(curit, (int)A.size() - 1); curit = max(curit, 0LL);
        while (curit != A.size() - 1 && A[curit] * 1LL * x + B[curit] >= A[curit + 1] * 1LL * x + B[curit + 1]) curit++;
        return A[curit] * 1LL * x + B[curit];
    }
};

ConvexHullTrick f[4 * N];
void init(int k, int l, int r) {
    f[k].init(1, 0);
    if (l == r) return;
    int mid = (l + r) / 2;
    init(k * 2, l, mid); init(k * 2 + 1, mid + 1, r);
}

void update(int k, int l, int r, const int L, const int R, const Line X) {
    if (r < L || R < l) return;
    if (L <= l && r <= R) {
        f[k].add(X.A, X.B);
        return;
    }
    int mid = (l + r) / 2;
    update(k * 2, l, mid, L, R, X); update(k * 2 + 1, mid + 1, r, L, R, X);
}

int get(int k, int l, int r, int pos, int X) {
    if (r < pos || pos < l) return -INF;
    int ret = -INF;
    if (!f[k].A.empty()) ret = f[k].query(X);
    if (l == r) return ret;
    int mid = (l + r) / 2;
    ret = max(ret, get(k * 2, l, mid, pos, X));
    ret = max(ret, get(k * 2 + 1, mid + 1, r, pos, X));
    return ret;
}

signed main() {
#ifndef UncleGrandpa
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#endif
    vector<Line> line; vector<int> where(N);
    vector<pair<int, int> > query;// pair Time, X
    int q;
    cin >> q;
    loop(Q, 1, q) {
        int type; cin >> type;
        if (type == 1) {
            Line X;
            cin >> X.A >> X.B; X.sta = Q; X.en = q;
            line.push_back(X); where[Q] = line.size() - 1;
        }
        else if (type == 2) {
            int t; cin >> t;
            line[where[t]].en = Q;
        }
        else if (type == 3) {
            int x; cin >> x;
            query.push_back(mp(Q, x));
        }
    }
    sort(line.begin(), line.end(), [&](Line X, Line Y) {
        return X.A < Y.A;
    });
    init(1, 1, q);
    for (auto it : line) {
        update(1, 1, q, it.sta, it.en, it);
    }
    for (auto it : query) {
        int rec = get(1, 1, q, it.fi, it.se);
        if (rec == -INF) cout << "EMPTY SET" << endl;
        else cout << rec << endl;
    }
}


/*input
7
3 1
1 2 3
3 1
1 -1 100
3 1
2 4
3 1

*/
#include <bits/stdc++.h>
using namespace std;
#define sp ' '
#define endl '\n'
#define fi first
#define se second
#define mp make_pair
#define __builtin_popcount __builtin_popcountll
#define int long long
#define bit(x,y) ((x>>y)&1LL)
#define loop(i,l,r) for(int i=(int)l; i<=(int)r; i++)
#define rloop(i,l,r) for(int i=(int)l; i>=(int)r; i--)
const int N = 300005;

void read(int &number) {
    bool negative = false;
    int c;
    number = 0;
    c = getchar();
    while (c == ' ' || c == '\n')
        c = getchar();
    if (c == '-') {
        negative = true;
        c = getchar();
    }
    for (; (c > 47 && c < 58); c = getchar())
        number = number * 10 + c - 48;
    if (negative)
        number = -number;
}

template <class T1, class T2>
ostream &operator<<(ostream &os, const pair<T1, T2> &a) {
    return os << '(' << a.first << ", " << a.second << ')';
}
template <class T>
ostream &operator<<(ostream &os, const vector<T> &a) {
    os << '[';
    for (unsigned int i = 0; i < a.size(); i++)
        os << a[i] << (i < a.size() - 1 ? ", " : "");
    os << ']';
    return os;
}
template <class T>
ostream &operator<<(ostream &os, const set<T> &a) {
    os << '{';
    for (typename set<T>::iterator it = a.begin(); it != a.end(); it++) {
        typename set<T>::iterator jt = it;
        os << *it << (++jt != a.end() ? ", " : "");
    }
    os << '}';
    return os;
}
template <class T1, class T2>
ostream &operator<<(ostream &os, map<T1, T2> &a) {
    os << "{\n";
    for (typename map<T1, T2>::iterator it = a.begin(); it != a.end(); it++) {
        typename map<T1, T2>::iterator jt = it;
        os << "  " << it->first << ": " << it->second << (++jt != a.end() ? ",\n" : "\n");
    }
    os << '}';
    return os;
}
struct Line {
    int A, B;
    int sta, en;
    Line(int _A, int _B, int _sta, int _en): A(_A), B(_B), sta(_sta), en(_en) {};
    Line() {};
};

const int INF = 4e18;
struct ConvexHullTrick {
    vector<int> A, B;
    bool increasing_slope, need_tenary;
    bool bad(int l1, int l2, int l3) {
        if (increasing_slope)
            return (B[l3] - B[l1]) * (A[l1] - A[l2]) < (A[l1] - A[l3]) * (B[l2] - B[l1]);
        return (B[l3] - B[l1]) * (A[l1] - A[l2]) > (A[l1] - A[l3]) * (B[l2] - B[l1]);
    }
    void init(bool _increasing_slope, bool _need_tenary) {
        increasing_slope = _increasing_slope; need_tenary = _need_tenary;
        A.clear(); B.clear();
    }
    void add(int x, int y) {
        if (!A.empty()) {
            if (A.back() == x && B.back() <= y) A.pop_back(), B.pop_back();
        }
        A.push_back(x);
        B.push_back(y);
        while (A.size() > 2 && bad(A.size() - 3, A.size() - 2, A.size() - 1)) {
            A.erase(A.end() - 2);
            B.erase(B.end() - 2);
        }
    }
    int curit = 0;
    int query(int x) {
        assert(!A.empty());
        if (!need_tenary) {
            curit = min(curit, (int)A.size() - 1);
            while (curit != A.size() - 1 && A[curit] * 1LL * x + B[curit] <= A[curit + 1] * 1LL * x + B[curit + 1]) curit++;
            return A[curit] * 1LL * x + B[curit];
        }
        int l = 0, r = (int)(A.size()) - 1;
        while (r - l > 2) {
            int mid1 = (l * 2 + r) / 3; int mid2 = (l + 2 * r) / 3;
            int val1 = A[mid1] * x + B[mid1]; int val2 = A[mid2] * x + B[mid2];
            if (val1 == val2)
                l = mid1, r = mid2;
            else if (val1 < val2)l = mid1;
            else r = mid2;
        }
        int ret = -1e18;
        for (int i = l; i <= r; i++)
            ret = max(ret, A[i] * x + B[i]);
        return ret;
    }
} CV;

ConvexHullTrick f[4 * N];
void init(int k, int l, int r) {
    f[k].init(1, 1);
    if (l == r) return;
    int mid = (l + r) / 2;
    init(k * 2, l, mid); init(k * 2 + 1, mid + 1, r);
}

void update(int k, int l, int r, const int L, const int R, const Line X) {
    if (r < L || R < l) return;
    if (L <= l && r <= R) {
        f[k].add(X.A, X.B);
        return;
    }
    int mid = (l + r) / 2;
    update(k * 2, l, mid, L, R, X); update(k * 2 + 1, mid + 1, r, L, R, X);
}

int get(int k, int l, int r, int pos, int X) {
    if (r < pos || pos < l) return -INF;
    int ret = -INF;
    if (!f[k].A.empty()) ret = f[k].query(X);
    if (l == r) return ret;
    int mid = (l + r) / 2;
    ret = max(ret, get(k * 2, l, mid, pos, X));
    ret = max(ret, get(k * 2 + 1, mid + 1, r, pos, X));
    return ret;
}

signed main() {
#ifndef UncleGrandpa
    ios_base::sync_with_stdio(false); cin.tie(0); cout.tie(0);
#endif
    vector<Line> line; vector<int> where(N);
    vector<pair<int, int> > query;// pair Time, X
    int q;
    cin >> q;
    loop(Q, 1, q) {
        int type; cin >> type;
        if (type == 1) {
            Line X;
            cin >> X.A >> X.B; X.sta = Q; X.en = q;
            line.push_back(X); where[Q] = line.size() - 1;
        }
        else if (type == 2) {
            int t; cin >> t;
            line[where[t]].en = Q;
        }
        else if (type == 3) {
            int x; cin >> x;
            query.push_back(mp(Q, x));
        }
    }
    sort(line.begin(), line.end(), [&](Line X, Line Y) {
        return X.A < Y.A;
    });
    init(1, 1, q);
    for (auto it : line) {
        update(1, 1, q, it.sta, it.en, it);
    }
    for (auto it : query) {
        int rec = get(1, 1, q, it.fi, it.se);
        if (rec == -INF) cout << "EMPTY SET" << endl;
        else cout << rec << endl;
    }
}


/********************************************
*                                           *
*    Solved By : Bir Bahadur Khatri(B'ru)   *
*      Be Positive,be Happy.                *
*                                           *
*********************************************/
#define ff first
#define D double
#define sz size()
#define ss second
#define PB push_back
#define MP make_pair
#define SQR(n) (n*n)
#define CHR getchar()
#define NL printf("\n")
#include<bits/stdc++.h>
#define ULL unsigned LL
#define PI 2.0*acos(0.0)
#define LL long long int
#define S1(a) a=in<int>()
#define SL1(a) a=in<LL>()
#define Max(a,b) ((a>b)?a:b)
#define Min(a,b) ((a<b)?a:b)
#define all(a) a.begin(),a.end()
#define _Max(a,b,c) Max(a,Max(b,c))
#define _Min(a,b,c) Min(a,Min(b,c))
#define SL2(a,b) a=in<LL>(),b=in<LL>()
#define F(i,a,b) for(int i=a;i<b; i++)
#define S2(a,b) a=in<int>(),b=in<int>()
#define R(i,a,b) for(int i=a-1;i>=b; i--)
#define BitCnt(a) __builtin_popcountll(a)
#define MEM(a,val) memset(a,val,sizeof(a))
#define SL3(a,b,c) a=in<LL>(),b=in<LL>(),c=in<LL>()
#define S3(a,b,c) a=in<int>(),b=in<int>(),c=in<int>()
#define _cin ios_base::sync_with_stdio(0); cin.tie(0)
#define cp printf("***** here here here here *****\n");
#define trace1(x)                cerr << #x << ": " << x << endl;
#define InpOut freopen("A.in","r",stdin),freopen("A1.out","w",stdout)
#define trace2(x, y)             cerr << #x << ": " << x << " | " << #y << ": " << y << endl;
#define trace3(x, y, z)          cerr << #x << ": " << x << " | " << #y << ": " << y << " | " << #z << ": " << z << endl;
#define trace4(a, b, c, d)       cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << endl;

using namespace std;
template <typename T> T in(){char ch;T n = 0;bool ng = false;while (1){ch = getchar();if (ch == '-'){ng = true;ch = getchar();break;}if (ch>='0' && ch<='9')     break;}while (1){n = n*10 + (ch - '0');ch = getchar();if (ch<'0' || ch>'9')   break;}return (ng?-n:n);}
template<typename T>inline T POW(T B,T P){ if(P==0) return 1; if(P&1) return B*POW(B,P-1);  else return SQR(POW(B,P/2));}
template<typename T>inline T Gcd(T a,T b){if(a<0)return Gcd(-a,b);if(b<0)return Gcd(a,-b);return (b==0)?a:Gcd(b,a%b);}
template<typename T>inline T Lcm(T a,T b) {if(a<0)return Lcm(-a,b);if(b<0)return Lcm(a,-b);return a*(b/Gcd(a,b));}
long long Bigmod(long long base, long long power, long long MOD){long long ret=1;while(power){if(power & 1)ret=(ret*base)%MOD;base=(base*base)%MOD;power>>=1;}return ret;}
bool isVowel(char ch){ ch=toupper(ch); if(ch=='A'||ch=='U'||ch=='I'||ch=='O'||ch=='E') return true; return false;}
template <typename T> LL isLeft(T a,T b,T c) {return(a.x-b.x)*(b.y-c.y)-(b.x-c.x)*(a.y-b.y);}
long long ModInverse(long long number, long long MOD){return Bigmod(number, MOD-2, MOD);}
bool isConst(char ch){if (isalpha(ch) && !isVowel(ch)) return true; return false;}
int toInt(string s)  { int sm; stringstream ss(s); ss>>sm; return sm; }
///**********************************************************//

#define MD1 1000000007ULL
#define MD2 1000000009ULL
#define MD3 1000000021ULL
#define BS1 10000019ULL
#define BS2 10000079ULL
#define BS3 10000103ULL
#define PUL pair<ULL,ULL>
#define PLL pair<LL,LL>
#define PII pair<int,int>

///         0123456789
#define MX  300007
#define MOD 1000000007
#define INF 2000000000000000000LL
#define EPS 1e-9

/// ==========================================////

struct line{
	long long a , b;
	double xleft;
	bool type;
	line(long long _a , long long _b){
		a = _a;
		b = _b;
		type = 0;
	}
	bool operator < (const line &other) const{
		if(other.type){
			return xleft < other.xleft;
		}
		return a > other.a;
	}
};
double meet(line x , line y){
	return 1.0 * (y.b - x.b) / (x.a - y.a);
}
struct cht{
	set < line > hull;
	cht(){
		hull.clear();
	}
	typedef set < line > :: iterator ite;
	bool hasleft(ite node){
		return node != hull.begin();
	}
	bool hasright(ite node){
		return node != prev(hull.end());
	}
	void updateborder(ite node){
		if(hasright(node)){
			line temp = *next(node);
			hull.erase(temp);
			temp.xleft = meet(*node , temp);
			hull.insert(temp);
		}
		if(hasleft(node)){
			line temp = *node;
			temp.xleft = meet(*prev(node) , temp);
			hull.erase(node);
			hull.insert(temp);
		}
		else{
			line temp = *node;
			hull.erase(node);
			temp.xleft = -2000000000000000000LL;
			hull.insert(temp);
		}
	}
	bool useless(line left , line middle , line right){
		double x = meet(left , right);
		double y = x * middle.a + middle.b;
		double ly = left.a * x + left.b;
		return y > ly;
	}
	bool useless(ite node){
		if(hasleft(node) && hasright(node)){
			return useless(*prev(node) , *node , *next(node));
		}
		return 0;
	}
	void addline(long long m , long long c){
		line temp = line(m , c);
		auto it = hull.lower_bound(temp);
		if(it != hull.end() && it -> a == m){
			if(it -> b > c){
				hull.erase(it);
			}
			else{
				return;
			}
		}
		hull.insert(temp);
		it = hull.find(temp);
		if(useless(it)){
			hull.erase(it);
			return;
		}
		while(hasleft(it) && useless(prev(it))){
			hull.erase(prev(it));
		}
		while(hasright(it) && useless(next(it))){
			hull.erase(next(it));
		}
		updateborder(it);
	}
	long long getbest(long long x){
		if(hull.empty()){
			return 2000000000000000000LL;
		}
		line query(0 , 0);
		query.xleft = x;
		query.type = 1;
		auto it = hull.lower_bound(query);
		it = prev(it);
		return it -> a * x + it -> b;
	}
};

cht Tree[MX*4];
LL m,c;
void Upd(int id,int l,int r,int st,int ed) {
    if(st<=l&&ed>=r) {
        Tree[id].addline(m,c);
        return;
    }

    int mid=(l+r)/2;
    int lft=2*id;
    int rgt=lft+1;

    if(ed<=mid)             Upd(lft,l,mid,st,ed);
    else if(st>mid)         Upd(rgt,mid+1,r,st,ed);
    else {
                            Upd(lft,l,mid,st,ed);
                            Upd(rgt,mid+1,r,st,ed);
    }
}

LL ans;
LL P;
void Qry(int id,int l,int r,int p) {
    ans=max(ans,Tree[id].getbest(P)*-1);
    if(l==r) {
        return;
    }
    int mid=(l+r)/2;
    int lft=2*id;
    int rgt=lft+1;
    if(p<=mid)          Qry(lft,l,mid,p);
    else                Qry(rgt,mid+1,r,p);
}

int ar[MX];
int X[MX];
int Y[MX];
int Tp[MX];
int br[MX];

int main(){

    int n;
    S1(n);

    F(i,1,n+1) {
        S2(Tp[i],ar[i]);
        if(Tp[i]==1) {
            S1(br[i]);
            Y[i]=n;
        }
        else if (Tp[i]==2) {
            Y[ ar[i] ]=i;
        }
    }

    F(i,1,n+1) {
        if(Tp[i]==1) {
            m=-ar[i],c=-br[i];
            Upd(1,1,n,i,Y[i]);
        }
        else if(Tp[i]==3) {
            P=ar[i];
            ans=-INF;
            Qry(1,1,n,i);
            if(ans==-INF) printf("EMPTY SET\n");
            else
            printf("%lld\n",ans);
        }
    }

    return 0;
}


/********************************************
*                                           *
*    Solved By : Bir Bahadur Khatri(B'ru)   *
*      Be Positive,be Happy.                *
*                                           *
*********************************************/
#define ff first
#define D double
#define sz size()
#define ss second
#define PB push_back
#define MP make_pair
#define SQR(n) (n*n)
#define CHR getchar()
#define NL printf("\n")
#include<bits/stdc++.h>
#define ULL unsigned LL
#define PI 2.0*acos(0.0)
#define LL long long int
#define S1(a) a=in<int>()
#define SL1(a) a=in<LL>()
#define Max(a,b) ((a>b)?a:b)
#define Min(a,b) ((a<b)?a:b)
#define all(a) a.begin(),a.end()
#define _Max(a,b,c) Max(a,Max(b,c))
#define _Min(a,b,c) Min(a,Min(b,c))
#define SL2(a,b) a=in<LL>(),b=in<LL>()
#define F(i,a,b) for(int i=a;i<b; i++)
#define S2(a,b) a=in<int>(),b=in<int>()
#define R(i,a,b) for(int i=a-1;i>=b; i--)
#define BitCnt(a) __builtin_popcountll(a)
#define MEM(a,val) memset(a,val,sizeof(a))
#define SL3(a,b,c) a=in<LL>(),b=in<LL>(),c=in<LL>()
#define S3(a,b,c) a=in<int>(),b=in<int>(),c=in<int>()
#define _cin ios_base::sync_with_stdio(0); cin.tie(0)
#define cp printf("***** here here here here *****\n");
#define trace1(x)                cerr << #x << ": " << x << endl;
#define InpOut freopen("A.in","r",stdin),freopen("A1.out","w",stdout)
#define trace2(x, y)             cerr << #x << ": " << x << " | " << #y << ": " << y << endl;
#define trace3(x, y, z)          cerr << #x << ": " << x << " | " << #y << ": " << y << " | " << #z << ": " << z << endl;
#define trace4(a, b, c, d)       cerr << #a << ": " << a << " | " << #b << ": " << b << " | " << #c << ": " << c << " | " << #d << ": " << d << endl;

using namespace std;
template <typename T> T in(){char ch;T n = 0;bool ng = false;while (1){ch = getchar();if (ch == '-'){ng = true;ch = getchar();break;}if (ch>='0' && ch<='9')     break;}while (1){n = n*10 + (ch - '0');ch = getchar();if (ch<'0' || ch>'9')   break;}return (ng?-n:n);}
template<typename T>inline T POW(T B,T P){ if(P==0) return 1; if(P&1) return B*POW(B,P-1);  else return SQR(POW(B,P/2));}
template<typename T>inline T Gcd(T a,T b){if(a<0)return Gcd(-a,b);if(b<0)return Gcd(a,-b);return (b==0)?a:Gcd(b,a%b);}
template<typename T>inline T Lcm(T a,T b) {if(a<0)return Lcm(-a,b);if(b<0)return Lcm(a,-b);return a*(b/Gcd(a,b));}
long long Bigmod(long long base, long long power, long long MOD){long long ret=1;while(power){if(power & 1)ret=(ret*base)%MOD;base=(base*base)%MOD;power>>=1;}return ret;}
bool isVowel(char ch){ ch=toupper(ch); if(ch=='A'||ch=='U'||ch=='I'||ch=='O'||ch=='E') return true; return false;}
template <typename T> LL isLeft(T a,T b,T c) {return(a.x-b.x)*(b.y-c.y)-(b.x-c.x)*(a.y-b.y);}
long long ModInverse(long long number, long long MOD){return Bigmod(number, MOD-2, MOD);}
bool isConst(char ch){if (isalpha(ch) && !isVowel(ch)) return true; return false;}
int toInt(string s)  { int sm; stringstream ss(s); ss>>sm; return sm; }
///**********************************************************//

#define MD1 1000000007ULL
#define MD2 1000000009ULL
#define MD3 1000000021ULL
#define BS1 10000019ULL
#define BS2 10000079ULL
#define BS3 10000103ULL
#define PUL pair<ULL,ULL>
#define PLL pair<LL,LL>
#define PII pair<int,int>

///         0123456789
#define MX  300007
#define MOD 1000000007
#define INF 2000000000000000000LL
#define EPS 1e-9

/// ==========================================////

struct line{
	long long a , b;
	double xleft;
	bool type;
	line(long long _a , long long _b){
		a = _a;
		b = _b;
		type = 0;
	}
	bool operator < (const line &other) const{
		if(other.type){
			return xleft < other.xleft;
		}
		return a > other.a;
	}
};
double meet(line x , line y){
	return 1.0 * (y.b - x.b) / (x.a - y.a);
}
struct cht{
	set < line > hull;
	cht(){
		hull.clear();
	}
	typedef set < line > :: iterator ite;
	bool hasleft(ite node){
		return node != hull.begin();
	}
	bool hasright(ite node){
		return node != prev(hull.end());
	}
	void updateborder(ite node){
		if(hasright(node)){
			line temp = *next(node);
			hull.erase(temp);
			temp.xleft = meet(*node , temp);
			hull.insert(temp);
		}
		if(hasleft(node)){
			line temp = *node;
			temp.xleft = meet(*prev(node) , temp);
			hull.erase(node);
			hull.insert(temp);
		}
		else{
			line temp = *node;
			hull.erase(node);
			temp.xleft = -2000000000000000000LL;
			hull.insert(temp);
		}
	}
	bool useless(line left , line middle , line right){
		double x = meet(left , right);
		double y = x * middle.a + middle.b;
		double ly = left.a * x + left.b;
		return y > ly;
	}
	bool useless(ite node){
		if(hasleft(node) && hasright(node)){
			return useless(*prev(node) , *node , *next(node));
		}
		return 0;
	}
	void addline(long long m , long long c){
		line temp = line(m , c);
		auto it = hull.lower_bound(temp);
		if(it != hull.end() && it -> a == m){
			if(it -> b > c){
				hull.erase(it);
			}
			else{
				return;
			}
		}
		hull.insert(temp);
		it = hull.find(temp);
		if(useless(it)){
			hull.erase(it);
			return;
		}
		while(hasleft(it) && useless(prev(it))){
			hull.erase(prev(it));
		}
		while(hasright(it) && useless(next(it))){
			hull.erase(next(it));
		}
		updateborder(it);
	}
	long long getbest(long long x){
		if(hull.empty()){
			return 2000000000000000000LL;
		}
		line query(0 , 0);
		query.xleft = x;
		query.type = 1;
		auto it = hull.lower_bound(query);
		it = prev(it);
		return it -> a * x + it -> b;
	}
};

cht Tree[MX*3];
LL m,c;
void Upd(int id,int l,int r,int st,int ed) {
    if(st<=l&&ed>=r) {
        Tree[id].addline(m,c);
        return;
    }

    int mid=(l+r)/2;
    int lft=2*id;
    int rgt=lft+1;

    if(ed<=mid)             Upd(lft,l,mid,st,ed);
    else if(st>mid)         Upd(rgt,mid+1,r,st,ed);
    else {
                            Upd(lft,l,mid,st,ed);
                            Upd(rgt,mid+1,r,st,ed);
    }
}

LL ans;
LL P;
void Qry(int id,int l,int r,int p) {
    ans=max(ans,Tree[id].getbest(P)*-1);
    if(l==r) {
        return;
    }
    int mid=(l+r)/2;
    int lft=2*id;
    int rgt=lft+1;
    if(p<=mid)          Qry(lft,l,mid,p);
    else                Qry(rgt,mid+1,r,p);
}

int ar[MX];
int X[MX];
int Y[MX];
int Tp[MX];
int br[MX];

int main(){

    int n;
    S1(n);

    F(i,1,n+1) {
        S2(Tp[i],ar[i]);
        if(Tp[i]==1) {
            S1(br[i]);
            Y[i]=n;
        }
        else if (Tp[i]==2) {
            Y[ ar[i] ]=i;
        }
    }

    F(i,1,n+1) {
        if(Tp[i]==1) {
            m=-ar[i],c=-br[i];
            Upd(1,1,n,i,Y[i]);
        }
        else if(Tp[i]==3) {
            P=ar[i];
            ans=-INF;
            Qry(1,1,n,i);
            if(ans==-INF) printf("EMPTY SET\n");
            else
            printf("%lld\n",ans);
        }
    }

    return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int magic = 550;

class MaxHull {
private:
    vector <long long> M, C;
    int pointer;
    bool bad(int l1, int l2, int l3) {
            return (C[l3] - C[l1]) * (M[l1] - M[l2]) < (C[l2] - C[l1]) * (M[l1] - M[l3]);
    }
public:
    MaxHull () {
        pointer = 0;
    }
    void addPoint (long long m, long long c) {
        M.push_back(m);
        C.push_back(c);
        while(M.size() >= 3 && bad(M.size() - 3, M.size() - 2, M.size() - 1)) {
            M.erase(M.end() - 2);
            C.erase(C.end() - 2);
        }
    }
    long long query(long long x) {
        if(M.empty()) return LONG_LONG_MIN;
        if(pointer >= (int) M.size()) pointer = M.size() - 1;
        while(pointer + 1 < (int) M.size() && M[pointer] * x + C[pointer] <= M[pointer + 1] * x + C[pointer + 1]) {
            pointer++;
        }
        return M[pointer] * x + C[pointer];
    }
    void init() {
        M.clear();
        C.clear();
        pointer = 0;
    }
};

class BruteHull {
private:
    vector <long long> M, C;
public:
    BruteHull () {}
    void erase(long long m, long long c) {
        int idx = -1;
        for(unsigned i = 0; i < M.size(); i++) {
            if(M[i] == m && C[i] == c) {
                idx = i;
                break;
            }
        }
        if(idx != -1) {
            M.erase(M.begin() + idx);
            C.erase(C.begin() + idx);
        }
    }
    void addPoint(long long m, long long c) {
        M.push_back(m);
        C.push_back(c);
    }
    long long query(long long x) {
        long long ans = LONG_LONG_MIN;
        for(unsigned i = 0; i < M.size(); i++) {
            ans = max(ans, M[i] * x + C[i]);
        }
        return ans;
    }
    void clear() {
        M.clear();
        C.clear();
    }
    void out() {
        for(unsigned i = 0; i < M.size(); i++) {
            cout << "(" << M[i] << " " << C[i] << ") ";
        }
        cout << endl;
    }
};

typedef pair <int, int> pii;

pii arr[300010];
int type[300010];

multiset <pii> S;
vector <int> block[550];
long long res[300010];

int main() {
    int q;
    scanf("%d", &q);
    for(int i = 0; i < q; i++) {
        block[i / magic].push_back(i);
    }
    int maxn = (q - 1) / magic;

    for(int i = 0; i < q; i++) {
        scanf("%d", &type[i]);
        arr[i].first = arr[i].second = -1;

        if(type[i] == 1) {
            scanf("%d %d", &arr[i].first, &arr[i].second);
        } else if (type[i] == 2) {
            scanf("%d", &arr[i].first);
            arr[i].first--;
        } else {
            scanf("%d", &arr[i].first);
        }
    }
    MaxHull Q;
    BruteHull B;

    for(int i = 0; i <= maxn; i++) {
        B.clear();
        for(unsigned j = 0; j < block[i].size(); j++) {
            int k = block[i][j];
            int idx = arr[k].first;
            if(type[k] == 2) {
                if(idx < i * magic) {
                    S.erase(S.find(arr[idx]));
                    B.addPoint(arr[idx].first, arr[idx].second);
                }
            }
        }
        Q.init();
        pii last = pii (INT_MAX, INT_MAX);
        for(auto j : S) {
            if(last == j) continue;
            last = j;
            Q.addPoint(j.first, j.second);
        }

        for(unsigned j = 0; j < block[i].size(); j++) {
            int k = block[i][j];
            int idx = arr[k].first;
            if(type[k] == 1) {
                B.addPoint(arr[k].first, arr[k].second);
            } else if (type[k] == 2) {
                B.erase(arr[idx].first, arr[idx].second);
            } else {
                res[k] = max(-Q.query(idx), B.query(idx));
            }
        }
        for(unsigned j = 0; j < block[i].size(); j++) {
            int k = block[i][j];
            int idx = arr[k].first;
            if(type[k] == 1) {
                S.insert(arr[k]);
            } else if (type[k] == 2) {
                if(idx >= i * magic) S.erase(S.find(arr[idx]));
            }
        }
    }
    for(int i = 0; i < q; i++) {
        if(type[i] == 3) {
            if(res[i] == LONG_LONG_MIN) printf("EMPTY SET\n");
            else printf("%lld\n", res[i]);
        }
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int magic = 550;

class MaxHull {
private:
    vector <long long> M, C;
    int pointer;
    bool bad(int p, int q, int r) {
        return (C[p] - C[q]) * (M[r] - M[p]) >= (C[p] - C[r]) * (M[q] - M[p]);
    }
public:
    MaxHull () {
        pointer = 0;
    }
    void addPoint (long long m, long long c) {
        M.push_back(m);
        C.push_back(c);
        while(M.size() >= 3 && bad(M.size() - 3, M.size() - 2, M.size() - 1)) {
            M.erase(M.end() - 2);
            C.erase(C.end() - 2);
        }
    }
    long long query(long long x) {
        if(M.empty()) return LONG_LONG_MIN;
        while(pointer + 1 < (int) M.size() && M[pointer] * x + C[pointer] <= M[pointer + 1] * x + C[pointer + 1]) {
            pointer++;
        }
        return M[pointer] * x + C[pointer];
    }
    void addSet (vector <int> p, vector <int> q) {
        M.clear(); C.clear(); pointer = 0;
        for(unsigned i = 0; i < p.size(); i++) {
            addPoint(p[i], q[i]);
        }
    }
};
class BruteHull {
private:
    vector <long long> M, C;
public:
    BruteHull () {}
    void erase(long long m, long long c) {
        int idx = -1;
        for(unsigned i = 0; i < M.size(); i++) {
            if(M[i] == m && C[i] == c) {
                idx = i;
                break;
            }
        }
        if(idx != -1) {
            M.erase(M.begin() + idx);
            C.erase(C.begin() + idx);
        }
    }
    void addPoint(long long m, long long c) {
        M.push_back(m);
        C.push_back(c);
    }
    long long query(long long x) {
        long long ans = LONG_LONG_MIN;
        for(unsigned i = 0; i < M.size(); i++) {
            ans = max(ans, M[i] * x + C[i]);
        }
        return ans;
    }
    void clear() {
        M.clear();
        C.clear();
    }
    void out() {
        for(unsigned i = 0; i < M.size(); i++) {
            cout << "(" << M[i] << " " << C[i] << ") ";
        }
        cout << endl;
    }
};

typedef pair <int, int> pii;

pii arr[300010];
int type[300010];

multiset <pii> S;
vector <int> block[550];
long long res[300010];

int main() {
    int q;
    scanf("%d", &q);
    for(int i = 0; i < q; i++) {
        block[i / magic].push_back(i);
    }
    int maxn = (q - 1) / magic;

    for(int i = 0; i < q; i++) {
        scanf("%d", &type[i]);
        arr[i].first = arr[i].second = -1;

        if(type[i] == 1) {
            scanf("%d %d", &arr[i].first, &arr[i].second);
        } else if (type[i] == 2) {
            scanf("%d", &arr[i].first);
            arr[i].first--;
        } else {
            scanf("%d", &arr[i].first);
        }
    }
    MaxHull Q;
    BruteHull B;

    for(int i = 0; i <= maxn; i++) {
        B.clear();
        for(unsigned j = 0; j < block[i].size(); j++) {
            int k = block[i][j];
            int idx = arr[k].first;
            if(type[k] == 2) {
                if(idx < i * magic) {
                    S.erase(S.find(arr[idx]));
                    B.addPoint(arr[idx].first, arr[idx].second);
                }
            }
        }
        vector <int> pp, qq;
        for(auto j : S) {
            pp.push_back(j.first);
            qq.push_back(j.second);
        }
        Q.addSet(pp, qq);

        for(unsigned j = 0; j < block[i].size(); j++) {
            int k = block[i][j];
            int idx = arr[k].first;
            if(type[k] == 1) {
                B.addPoint(arr[k].first, arr[k].second);
            } else if (type[k] == 2) {
                B.erase(arr[idx].first, arr[idx].second);
            } else {
                res[k] = max(Q.query(idx), B.query(idx));
            }
        }
        for(unsigned j = 0; j < block[i].size(); j++) {
            int k = block[i][j];
            int idx = arr[k].first;
            if(type[k] == 1) {
                S.insert(arr[k]);
            } else if (type[k] == 2) {
                if(idx >= i * magic) S.erase(S.find(arr[idx]));
            }
        }
    }

    for(int i = 0; i < q; i++) {
        if(type[i] == 3) {
            if(res[i] == LONG_LONG_MIN) printf("EMPTY SET\n");
            else printf("%lld\n", res[i]);
        }
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int magic = 550;

class MaxHull {
private:
    vector <long long> M, C;
    int pointer;
    bool bad(int p, int q, int r) {
        return (C[p] - C[q]) * (M[r] - M[p]) > (C[p] - C[r]) * (M[q] - M[p]);
    }
public:
    MaxHull () {
        pointer = 0;
    }
    void addPoint (long long m, long long c) {
        M.push_back(m);
        C.push_back(c);
        while(M.size() >= 3 && bad(M.size() - 3, M.size() - 2, M.size() - 1)) {
            M.erase(M.end() - 2);
            C.erase(C.end() - 2);
        }
    }
    long long query(long long x) {
        if(M.empty()) return LONG_LONG_MIN;
        if(pointer >= (int) M.size()) pointer = M.size() - 1;
        while(pointer + 1 < (int) M.size() && M[pointer] * x + C[pointer] <= M[pointer + 1] * x + C[pointer + 1]) {
            pointer++;
        }
        return M[pointer] * x + C[pointer];
    }
    void init() {
        M.clear();
        C.clear();
        pointer = 0;
    }
};

class BruteHull {
private:
    vector <long long> M, C;
public:
    BruteHull () {}
    void erase(long long m, long long c) {
        int idx = -1;
        for(unsigned i = 0; i < M.size(); i++) {
            if(M[i] == m && C[i] == c) {
                idx = i;
                break;
            }
        }
        if(idx != -1) {
            M.erase(M.begin() + idx);
            C.erase(C.begin() + idx);
        }
    }
    void addPoint(long long m, long long c) {
        M.push_back(m);
        C.push_back(c);
    }
    long long query(long long x) {
        long long ans = LONG_LONG_MIN;
        for(unsigned i = 0; i < M.size(); i++) {
            ans = max(ans, M[i] * x + C[i]);
        }
        return ans;
    }
    void clear() {
        M.clear();
        C.clear();
    }
    void out() {
        for(unsigned i = 0; i < M.size(); i++) {
            cout << "(" << M[i] << " " << C[i] << ") ";
        }
        cout << endl;
    }
};

typedef pair <int, int> pii;

pii arr[300010];
int type[300010];

multiset <pii> S;
vector <int> block[550];
long long res[300010];

int main() {
    int q;
    scanf("%d", &q);
    for(int i = 0; i < q; i++) {
        block[i / magic].push_back(i);
    }
    int maxn = (q - 1) / magic;

    for(int i = 0; i < q; i++) {
        scanf("%d", &type[i]);
        arr[i].first = arr[i].second = -1;

        if(type[i] == 1) {
            scanf("%d %d", &arr[i].first, &arr[i].second);
        } else if (type[i] == 2) {
            scanf("%d", &arr[i].first);
            arr[i].first--;
        } else {
            scanf("%d", &arr[i].first);
        }
    }
    MaxHull Q;
    BruteHull B;

    for(int i = 0; i <= maxn; i++) {
        B.clear();
        for(unsigned j = 0; j < block[i].size(); j++) {
            int k = block[i][j];
            int idx = arr[k].first;
            if(type[k] == 2) {
                if(idx < i * magic) {
                    S.erase(S.find(arr[idx]));
                    B.addPoint(arr[idx].first, arr[idx].second);
                }
            }
        }
        Q.init();
        for(auto j : S) {
            Q.addPoint(j.first, j.second);
        }

        for(unsigned j = 0; j < block[i].size(); j++) {
            int k = block[i][j];
            int idx = arr[k].first;
            if(type[k] == 1) {
                B.addPoint(arr[k].first, arr[k].second);
            } else if (type[k] == 2) {
                B.erase(arr[idx].first, arr[idx].second);
            } else {
                res[k] = max(-Q.query(idx), B.query(idx));
            }
        }
        for(unsigned j = 0; j < block[i].size(); j++) {
            int k = block[i][j];
            int idx = arr[k].first;
            if(type[k] == 1) {
                S.insert(arr[k]);
            } else if (type[k] == 2) {
                if(idx >= i * magic) S.erase(S.find(arr[idx]));
            }
        }
    }
    for(int i = 0; i < q; i++) {
        if(type[i] == 3) {
            if(res[i] == LONG_LONG_MIN) printf("EMPTY SET\n");
            else printf("%lld\n", res[i]);
        }
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int magic = 550;

class MaxHull {
private:
    vector <long long> M, C;
    int pointer;
    bool bad(int l1, int l2, int l3) {
            return (C[l3] - C[l1]) * (M[l1] - M[l2]) < (C[l2] - C[l1]) * (M[l1] - M[l3]);
    }
public:
    MaxHull () {
        pointer = 0;
    }
    void addPoint (long long m, long long c) {
        M.push_back(m);
        C.push_back(c);
        while(M.size() >= 3 && bad(M.size() - 3, M.size() - 2, M.size() - 1)) {
            M.erase(M.end() - 2);
            C.erase(C.end() - 2);
        }
    }
    long long query(long long x) {
        if(M.empty()) return LONG_LONG_MIN;
        if(pointer >= (int) M.size()) pointer = M.size() - 1;
        while(pointer + 1 < (int) M.size() && M[pointer] * x + C[pointer] <= M[pointer + 1] * x + C[pointer + 1]) {
            pointer++;
        }
        return M[pointer] * x + C[pointer];
    }
    void init() {
        M.clear();
        C.clear();
        pointer = 0;
    }
};

class BruteHull {
private:
    vector <long long> M, C;
public:
    BruteHull () {}
    void erase(long long m, long long c) {
        int idx = -1;
        for(unsigned i = 0; i < M.size(); i++) {
            if(M[i] == m && C[i] == c) {
                idx = i;
                break;
            }
        }
        if(idx != -1) {
            M.erase(M.begin() + idx);
            C.erase(C.begin() + idx);
        }
    }
    void addPoint(long long m, long long c) {
        M.push_back(m);
        C.push_back(c);
    }
    long long query(long long x) {
        long long ans = LONG_LONG_MIN;
        for(unsigned i = 0; i < M.size(); i++) {
            ans = max(ans, M[i] * x + C[i]);
        }
        return ans;
    }
    void clear() {
        M.clear();
        C.clear();
    }
    void out() {
        for(unsigned i = 0; i < M.size(); i++) {
            cout << "(" << M[i] << " " << C[i] << ") ";
        }
        cout << endl;
    }
};

typedef pair <int, int> pii;

pii arr[300010];
int type[300010];

multiset <pii> S;
vector <int> block[550];
long long res[300010];

int main() {
    int q;
    scanf("%d", &q);
    for(int i = 0; i < q; i++) {
        block[i / magic].push_back(i);
    }
    int maxn = (q - 1) / magic;

    for(int i = 0; i < q; i++) {
        scanf("%d", &type[i]);
        arr[i].first = arr[i].second = -1;

        if(type[i] == 1) {
            scanf("%d %d", &arr[i].first, &arr[i].second);
        } else if (type[i] == 2) {
            scanf("%d", &arr[i].first);
            arr[i].first--;
        } else {
            scanf("%d", &arr[i].first);
        }
    }
    MaxHull Q;
    BruteHull B;

    for(int i = 0; i <= maxn; i++) {
        B.clear();
        for(unsigned j = 0; j < block[i].size(); j++) {
            int k = block[i][j];
            int idx = arr[k].first;
            if(type[k] == 2) {
                if(idx < i * magic) {
                    S.erase(S.find(arr[idx]));
                    B.addPoint(arr[idx].first, arr[idx].second);
                }
            }
        }
        Q.init();
        for(auto j : S) {
            Q.addPoint(j.first, j.second);
        }

        for(unsigned j = 0; j < block[i].size(); j++) {
            int k = block[i][j];
            int idx = arr[k].first;
            if(type[k] == 1) {
                B.addPoint(arr[k].first, arr[k].second);
            } else if (type[k] == 2) {
                B.erase(arr[idx].first, arr[idx].second);
            } else {
                res[k] = max(-Q.query(idx), B.query(idx));
            }
        }
        for(unsigned j = 0; j < block[i].size(); j++) {
            int k = block[i][j];
            int idx = arr[k].first;
            if(type[k] == 1) {
                S.insert(arr[k]);
            } else if (type[k] == 2) {
                if(idx >= i * magic) S.erase(S.find(arr[idx]));
            }
        }
    }
    for(int i = 0; i < q; i++) {
        if(type[i] == 3) {
            if(res[i] == LONG_LONG_MIN) printf("EMPTY SET\n");
            else printf("%lld\n", res[i]);
        }
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int magic = 550;

/*
class MaxHull {
private:
    vector <long long> M, C;
    int pointer;
    bool bad(int p, int q, int r) {
        return (C[p] - C[q]) * (M[r] - M[p]) >= (C[p] - C[r]) * (M[q] - M[p]);
    }
public:
    MaxHull () {
        pointer = 0;
    }
    void addPoint (long long m, long long c) {
        M.push_back(m);
        C.push_back(c);
        while(M.size() >= 3 && bad(M.size() - 3, M.size() - 2, M.size() - 1)) {
            M.erase(M.end() - 2);
            C.erase(C.end() - 2);
        }
    }
    long long query(long long x) {
        if(M.empty()) return LONG_LONG_MIN;
        while(pointer + 1 < (int) M.size() && M[pointer] * x + C[pointer] <= M[pointer + 1] * x + C[pointer + 1]) {
            pointer++;
        }
        return M[pointer] * x + C[pointer];
    }
    void addSet (vector <int> p, vector <int> q) {
        M.clear(); C.clear(); pointer = 0;
        for(unsigned i = 0; i < p.size(); i++) {
            addPoint(p[i], q[i]);
        }
    }
};
*/

struct MaxHull {
    struct Line{
	   int a;
	   long long b;
	   long long val;
	   double xLeft;
	   bool type;
	   Line(long long _a = 0 , long long _b = 0){
		  a = _a;
		  b = _b;
		  xLeft = -2*(1e18);
		  type = 0;
		  val = 0;
	   }
	   long long valueAt(int x) const{
		  return 1LL * a * x + b;
	   }
	   friend bool areParallel(const Line &l1, const Line &l2){
		  return l1.a == l2.a;
	   }
	   friend double intersectX(const Line &l1 , const Line &l2){
		  return areParallel(l1 , l2) ? 2*(1e18) : 1.0 * (l2.b - l1.b) / (l1.a - l2.a);
	   }
	   bool operator < (const Line &l2) const{
		  if(!l2.type)
			 return a < l2.a;
		  return xLeft > l2.val;
	   }
    };
    set < Line >  hull;
    void init(){
    	hull.clear();
    }
    bool hasPrev(set < Line > :: iterator it){
	   return it != hull.begin();
    }
    bool hasNext(set < Line > :: iterator it){
	   return it != hull.end() && next(it) != hull.end();
    }
    bool irrelevant(const Line &l1 , const Line &l2 , const Line &l3){
	   return intersectX(l1,l3) <= intersectX(l1,l2);
    }
    bool irrelevant(set < Line > :: iterator it){
	   return hasPrev(it) && hasNext(it) && (irrelevant(*next(it) , *it , *prev(it)));
    }
    set < Line > :: iterator updateLeftBorder(set < Line > :: iterator it){
	   if(!hasNext(it)){
		  return it;
	   }
	   double val = intersectX(*it , *next(it));
	   Line buf(*it);
	   it = hull.erase(it);
	   buf.xLeft = val;
	   it = hull.insert(it, buf);
	   return it;
    }
    void addPoint(int a , long long b){
	   Line l3 = Line(a, b);
	   auto it = hull.lower_bound(l3);
	   if(it != hull.end() && areParallel(*it , l3)){
		  if(it -> b > b){
			 it = hull.erase(it);
		  }
		  else{
			 return;
		  }
	   }
	   it = hull.insert(it, l3);
	   if(irrelevant(it)){
		  hull.erase(it);
		  return;
	   }
	   while(hasPrev(it) && irrelevant(prev(it))){
		  hull.erase(prev(it));
	   }
	   while(hasNext(it) && irrelevant(next(it))){
		  hull.erase(next(it));
	   }
	   it = updateLeftBorder(it);
	   if(hasPrev(it)){
		  updateLeftBorder(prev(it));
	   }
	   if(hasNext(it)){
		  updateLeftBorder(next(it));
	   }
    }
    long long query(int x){
	   Line q;
	   q.val = x;
	   q.type = 1;
	   auto bestLine = hull.lower_bound(q);
	   if(bestLine == hull.end()){
		  return LONG_LONG_MIN;
	   }
	   return bestLine -> valueAt(x);
    }
};

class BruteHull {
private:
    vector <long long> M, C;
public:
    BruteHull () {}
    void erase(long long m, long long c) {
        int idx = -1;
        for(unsigned i = 0; i < M.size(); i++) {
            if(M[i] == m && C[i] == c) {
                idx = i;
                break;
            }
        }
        if(idx != -1) {
            M.erase(M.begin() + idx);
            C.erase(C.begin() + idx);
        }
    }
    void addPoint(long long m, long long c) {
        M.push_back(m);
        C.push_back(c);
    }
    long long query(long long x) {
        long long ans = LONG_LONG_MIN;
        for(unsigned i = 0; i < M.size(); i++) {
            ans = max(ans, M[i] * x + C[i]);
        }
        return ans;
    }
    void clear() {
        M.clear();
        C.clear();
    }
    void out() {
        for(unsigned i = 0; i < M.size(); i++) {
            cout << "(" << M[i] << " " << C[i] << ") ";
        }
        cout << endl;
    }
};

typedef pair <int, int> pii;

pii arr[300010];
int type[300010];

multiset <pii> S;
vector <int> block[550];
long long res[300010];

int main() {
    int q;
    scanf("%d", &q);
    for(int i = 0; i < q; i++) {
        block[i / magic].push_back(i);
    }
    int maxn = (q - 1) / magic;

    for(int i = 0; i < q; i++) {
        scanf("%d", &type[i]);
        arr[i].first = arr[i].second = -1;

        if(type[i] == 1) {
            scanf("%d %d", &arr[i].first, &arr[i].second);
        } else if (type[i] == 2) {
            scanf("%d", &arr[i].first);
            arr[i].first--;
        } else {
            scanf("%d", &arr[i].first);
        }
    }
    MaxHull Q;
    BruteHull B;

    for(int i = 0; i <= maxn; i++) {
        B.clear();
        for(unsigned j = 0; j < block[i].size(); j++) {
            int k = block[i][j];
            int idx = arr[k].first;
            if(type[k] == 2) {
                if(idx < i * magic) {
                    S.erase(S.find(arr[idx]));
                    B.addPoint(arr[idx].first, arr[idx].second);
                }
            }
        }
        Q.init();
        for(auto j : S) {
            Q.addPoint(-j.first, -j.second);
        }

        for(unsigned j = 0; j < block[i].size(); j++) {
            int k = block[i][j];
            int idx = arr[k].first;
            if(type[k] == 1) {
                B.addPoint(arr[k].first, arr[k].second);
            } else if (type[k] == 2) {
                B.erase(arr[idx].first, arr[idx].second);
            } else {
                res[k] = max(-Q.query(idx), B.query(idx));
            }
        }
        for(unsigned j = 0; j < block[i].size(); j++) {
            int k = block[i][j];
            int idx = arr[k].first;
            if(type[k] == 1) {
                S.insert(arr[k]);
            } else if (type[k] == 2) {
                if(idx >= i * magic) S.erase(S.find(arr[idx]));
            }
        }
    }
    for(int i = 0; i < q; i++) {
        if(type[i] == 3) {
            if(res[i] == LONG_LONG_MIN) printf("EMPTY SET\n");
            else printf("%lld\n", res[i]);
        }
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
const int magic = 550;

class MaxHull {
private:
    vector <long long> M, C;
    int pointer;
    bool bad(int p, int q, int r) {
        return (C[p] - C[q]) * (M[r] - M[p]) <= (C[p] - C[r]) * (M[q] - M[p]);
    }
public:
    MaxHull () {
        pointer = 0;
    }
    void addPoint (long long m, long long c) {
        M.push_back(m);
        C.push_back(c);
        while(M.size() >= 3 && bad(M.size() - 3, M.size() - 2, M.size() - 1)) {
            M.erase(M.end() - 2);
            C.erase(C.end() - 2);
        }
    }
    long long query(long long x) {
        if(M.empty()) return LONG_LONG_MIN;
        while(pointer + 1 < (int) M.size() && M[pointer] * x + C[pointer] <= M[pointer + 1] * x + C[pointer + 1]) {
            pointer++;
        }
        return M[pointer] * x + C[pointer];
    }
    void init() {
        M.clear();
        C.clear();
        pointer = 0;
    }
};

class BruteHull {
private:
    vector <long long> M, C;
public:
    BruteHull () {}
    void erase(long long m, long long c) {
        int idx = -1;
        for(unsigned i = 0; i < M.size(); i++) {
            if(M[i] == m && C[i] == c) {
                idx = i;
                break;
            }
        }
        if(idx != -1) {
            M.erase(M.begin() + idx);
            C.erase(C.begin() + idx);
        }
    }
    void addPoint(long long m, long long c) {
        M.push_back(m);
        C.push_back(c);
    }
    long long query(long long x) {
        long long ans = LONG_LONG_MIN;
        for(unsigned i = 0; i < M.size(); i++) {
            ans = max(ans, M[i] * x + C[i]);
        }
        return ans;
    }
    void clear() {
        M.clear();
        C.clear();
    }
    void out() {
        for(unsigned i = 0; i < M.size(); i++) {
            cout << "(" << M[i] << " " << C[i] << ") ";
        }
        cout << endl;
    }
};

typedef pair <int, int> pii;

pii arr[300010];
int type[300010];

multiset <pii> S;
vector <int> block[550];
long long res[300010];

int main() {
    int q;
    scanf("%d", &q);
    for(int i = 0; i < q; i++) {
        block[i / magic].push_back(i);
    }
    int maxn = (q - 1) / magic;

    for(int i = 0; i < q; i++) {
        scanf("%d", &type[i]);
        arr[i].first = arr[i].second = -1;

        if(type[i] == 1) {
            scanf("%d %d", &arr[i].first, &arr[i].second);
        } else if (type[i] == 2) {
            scanf("%d", &arr[i].first);
            arr[i].first--;
        } else {
            scanf("%d", &arr[i].first);
        }
    }
    MaxHull Q;
    BruteHull B;

    for(int i = 0; i <= maxn; i++) {
        B.clear();
        for(unsigned j = 0; j < block[i].size(); j++) {
            int k = block[i][j];
            int idx = arr[k].first;
            if(type[k] == 2) {
                if(idx < i * magic) {
                    S.erase(S.find(arr[idx]));
                    B.addPoint(arr[idx].first, arr[idx].second);
                }
            }
        }
        Q.init();
        for(auto j : S) {
            Q.addPoint(j.first, j.second);
        }

        for(unsigned j = 0; j < block[i].size(); j++) {
            int k = block[i][j];
            int idx = arr[k].first;
            if(type[k] == 1) {
                B.addPoint(arr[k].first, arr[k].second);
            } else if (type[k] == 2) {
                B.erase(arr[idx].first, arr[idx].second);
            } else {
                res[k] = max(-Q.query(idx), B.query(idx));
            }
        }
        for(unsigned j = 0; j < block[i].size(); j++) {
            int k = block[i][j];
            int idx = arr[k].first;
            if(type[k] == 1) {
                S.insert(arr[k]);
            } else if (type[k] == 2) {
                if(idx >= i * magic) S.erase(S.find(arr[idx]));
            }
        }
    }
    for(int i = 0; i < q; i++) {
        if(type[i] == 3) {
            if(res[i] == LONG_LONG_MIN) printf("EMPTY SET\n");
            else printf("%lld\n", res[i]);
        }
    }
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
typedef long long lint;
typedef long double llf;
typedef pair<int, int> pi;
typedef vector<int> vi;

vector<pi> tree[1050000];

void add(int s, int e, int ps, int pe, int p, pi v){
	if(e < ps || pe < s) return;
	if(s <= ps && pe <= e){
		tree[p].push_back(v);
		return;
	}
	int pm = (ps + pe) / 2;
	add(s, e, ps, pm, 2*p, v);
	add(s, e, pm+1, pe, 2*p+1, v);
}

vector<pi> tmp;

bool ok(pi a, pi b, pi c){
	return 1ll * (b.first - a.first) * (c.second - b.second) <= 1ll * (b.first - c.first) * (a.second - b.second);
}

void solve(int x){
	sort(tree[x].begin(), tree[x].end(), [&](const pi &a, const pi &b){
		return pi(a.first, -a.second) < pi(b.first, -b.second);
	});
	tmp.clear();
	int pv = -2e9;
	for(auto &i : tree[x]){
		if(i.first == pv) continue;
		pv = i.first;
		while(tmp.size() >= 2 && !ok(tmp[tmp.size()-2], tmp.back(), i)){
			tmp.pop_back();
		}
		tmp.push_back(i);
	}
	tree[x] = tmp;
}

void dfs(int s, int e, int p){
	solve(p);
	if(s == e) return;
	int m = (s+e)/2;
	dfs(s, m, 2*p);
	dfs(m+1, e, 2*p+1);
}

lint nodequery(int p, int x){
	if(tree[p].empty()) return -5e18;
	auto func = [&](int q){
		return 1ll * tree[p][q].first * x + tree[p][q].second;
	};
	int s = 0, e = (int)tree[p].size() - 1;
	while(s != e){
		int m = (s+e)/2;
		if(func(m) < func(m+1)) s = m+1;
		else e = m;
	}
	return func(s);
}

lint query(int pos, int s, int e, int p, int x){
	lint ret = nodequery(p, x);
	if(s == e) return ret;
	int m = (s+e)/2;
	if(pos <= m) ret = max(ret, query(pos, s, m, 2*p, x));
	else ret = max(ret, query(pos, m+1, e, 2*p+1, x));
	return ret;
}

struct ins{
	int s, e, x, y;
};

int q;
vector<ins> inserts;
pi inslis[300005];
bool vis[300005];
int cnt[300005], qry[300005];

int main(){
	int inp;
	cin >> inp;
	for(int i=1; i<=inp; i++){
		int t;
		scanf("%d",&t);
		if(t == 1){
			vis[i] = 1;
			scanf("%d %d",&inslis[i].first, &inslis[i].second);
		}
		if(t == 2){
			int x;
			scanf("%d",&x);
			inserts.push_back({cnt[x] + 1, cnt[i-1], inslis[x].first, inslis[x].second});
			vis[x] = 0;
		}
		if(t == 3){
			scanf("%d",&qry[i]);
			cnt[i]++;
		}
		cnt[i] += cnt[i-1];
	}
	if(cnt[inp] == 0) return 0;
	for(int i=1; i<=inp; i++){
		if(vis[i]){
			inserts.push_back({cnt[i] + 1, cnt[inp], inslis[i].first, inslis[i].second});
		}
	}
	for(auto &i : inserts){
		add(i.s, i.e, 1, cnt[inp], 1, pi(i.x, i.y));
	}
	dfs(1, cnt[inp], 1);
	for(int i=1; i<=inp; i++){
		if(cnt[i] != cnt[i-1]){
			lint t = query(cnt[i], 1, cnt[inp], 1, qry[i]);
			if(t < -4e18) puts("EMPTY SET");
			else printf("%lld\n", t);
		}
	}
}


#include <bits/stdc++.h>
using namespace std;
const int magic = 550;

class MaxHull {
private:
    vector <long long> M, C;
    int pointer;
    bool bad(int p, int q, int r) {
        return (C[p] - C[q]) * (M[r] - M[p]) < (C[p] - C[r]) * (M[q] - M[p]);
    }
public:
    MaxHull () {
        pointer = 0;
    }
    void addPoint (long long m, long long c) {
        M.push_back(m);
        C.push_back(c);
        while(M.size() >= 3 && bad(M.size() - 3, M.size() - 2, M.size() - 1)) {
            M.erase(M.end() - 2);
            C.erase(C.end() - 2);
        }
    }
    long long query(long long x) {
        if(M.empty()) return LONG_LONG_MIN;
        if(pointer >= (int) M.size()) pointer = M.size() - 1;
        while(pointer + 1 < (int) M.size() && M[pointer] * x + C[pointer] <= M[pointer + 1] * x + C[pointer + 1]) {
            pointer++;
        }
        return M[pointer] * x + C[pointer];
    }
    void init() {
        M.clear();
        C.clear();
        pointer = 0;
    }
};

class BruteHull {
private:
    vector <long long> M, C;
public:
    BruteHull () {}
    void erase(long long m, long long c) {
        int idx = -1;
        for(unsigned i = 0; i < M.size(); i++) {
            if(M[i] == m && C[i] == c) {
                idx = i;
                break;
            }
        }
        if(idx != -1) {
            M.erase(M.begin() + idx);
            C.erase(C.begin() + idx);
        }
    }
    void addPoint(long long m, long long c) {
        M.push_back(m);
        C.push_back(c);
    }
    long long query(long long x) {
        long long ans = LONG_LONG_MIN;
        for(unsigned i = 0; i < M.size(); i++) {
            ans = max(ans, M[i] * x + C[i]);
        }
        return ans;
    }
    void clear() {
        M.clear();
        C.clear();
    }
    void out() {
        for(unsigned i = 0; i < M.size(); i++) {
            cout << "(" << M[i] << " " << C[i] << ") ";
        }
        cout << endl;
    }
};

typedef pair <int, int> pii;

pii arr[300010];
int type[300010];

multiset <pii> S;
vector <int> block[550];
long long res[300010];

int main() {
    int q;
    scanf("%d", &q);
    for(int i = 0; i < q; i++) {
        block[i / magic].push_back(i);
    }
    int maxn = (q - 1) / magic;

    for(int i = 0; i < q; i++) {
        scanf("%d", &type[i]);
        arr[i].first = arr[i].second = -1;

        if(type[i] == 1) {
            scanf("%d %d", &arr[i].first, &arr[i].second);
        } else if (type[i] == 2) {
            scanf("%d", &arr[i].first);
            arr[i].first--;
        } else {
            scanf("%d", &arr[i].first);
        }
    }
    MaxHull Q;
    BruteHull B;

    for(int i = 0; i <= maxn; i++) {
        B.clear();
        for(unsigned j = 0; j < block[i].size(); j++) {
            int k = block[i][j];
            int idx = arr[k].first;
            if(type[k] == 2) {
                if(idx < i * magic) {
                    S.erase(S.find(arr[idx]));
                    B.addPoint(arr[idx].first, arr[idx].second);
                }
            }
        }
        Q.init();
        for(auto j : S) {
            Q.addPoint(j.first, j.second);
        }

        for(unsigned j = 0; j < block[i].size(); j++) {
            int k = block[i][j];
            int idx = arr[k].first;
            if(type[k] == 1) {
                B.addPoint(arr[k].first, arr[k].second);
            } else if (type[k] == 2) {
                B.erase(arr[idx].first, arr[idx].second);
            } else {
                res[k] = max(-Q.query(idx), B.query(idx));
            }
        }
        for(unsigned j = 0; j < block[i].size(); j++) {
            int k = block[i][j];
            int idx = arr[k].first;
            if(type[k] == 1) {
                S.insert(arr[k]);
            } else if (type[k] == 2) {
                if(idx >= i * magic) S.erase(S.find(arr[idx]));
            }
        }
    }
    for(int i = 0; i < q; i++) {
        if(type[i] == 3) {
            if(res[i] == LONG_LONG_MIN) printf("EMPTY SET\n");
            else printf("%lld\n", res[i]);
        }
    }
    return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll read(){
	ll a=0,b=getchar(),c=1;
	while(!isdigit(b))c=b=='-'?-1:1,b=getchar();
	while(isdigit(b))a=a*10+b-'0',b=getchar();
	return a*c;
}
const int M=3e5+5;
struct node{
	ll x,y,id;
	bool operator <(const node &A)const{
		if(x!=A.x)return x<A.x;
		return y<A.y;
	}
}s[M];
ll n,a[M],q[M],ki[M],st[M],ed[M],ans[M];
ll gg(ll k,ll ab){
	int l=1,r=ab;
	while(l<r){
		int mid=l+r>>1;
		if(k*s[q[mid]].x+s[q[mid]].y>k*s[q[mid+1]].x+s[q[mid+1]].y)r=mid;
		else l=mid+1;
	}
	if(ab)return k*s[q[l]].x+s[q[l]].y;
	return -3e18;
}
void query(ll l,ll r,ll ab){
	for(int i=l;i<=r;i++)
		if(a[s[i].id]==3)
			ans[s[i].id]=max(ans[s[i].id],gg(ki[s[i].id],ab));
}
void gao(ll l,ll r){
	if(l==r)return ;
	int mid=l+r>>1;
	gao(l,mid),gao(mid+1,r);
	sort(s+l,s+mid+1);
	int ab=0;
	for(int i=l;i<=mid;i++){
		if(a[s[i].id]!=1 or ed[s[i].id]<=r)continue;
		while(ab>1 and(s[i].y-s[q[ab]].y)*(s[i].x-s[q[ab-1]].x)>=(s[i].x-s[q[ab]].x)*(s[i].y-s[q[ab-1]].y))
			ab--;
		q[++ab]=i;
	}
	query(mid+1,r,ab);
	sort(s+mid+1,s+r+1);
	ab=0;
	for(int i=mid+1;i<=r;i++){
		if(a[s[i].id]!=2 or st[s[i].id]>=l)continue;
		while(ab>1 and(s[i].y-s[q[ab]].y)*(s[i].x-s[q[ab-1]].x)>=(s[i].x-s[q[ab]].x)*(s[i].y-s[q[ab-1]].y))
			ab--;
		q[++ab]=i;
	}
	query(l,mid,ab);
}
int main(){
	n=read();
	for(int i=1;i<=n;i++){
		ans[i]=-3e18,a[i]=read(),s[i].id=i;
		if(a[i]==1){
			s[i].x=read(),s[i].y=read();
			ed[i]=n+1;
		}
		else if(a[i]==3)ki[i]=read();
		else{
			int x=read();
			s[i].x=s[x].x;
			s[i].y=s[x].y;
			ed[x]=i,st[i]=x;
		}
	}
	gao(1,n);
	for(int i=1;i<=n;i++)
		if(a[i]==3){
			if(ans[i]==-3e18)puts("EMPTY SET");
			else printf("%lld\n",ans[i]);
		}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll read(){
	ll a=0,b=getchar(),c=1;
	while(!isdigit(b))c=b=='-'?-1:1,b=getchar();
	while(isdigit(b))a=a*10+b-'0',b=getchar();
	return a*c;
}
const int M=3e5+5;
struct node{
	ll x,y,id;
	bool operator <(const node &A)const{
		if(x!=A.x)return x<A.x;
		return y<A.y;
	}
}s[M];
ll n,a[M],q[M],ki[M],st[M],ed[M],ans[M];
ll gg(ll k,ll ab){
	int l=1,r=ab;
	while(l<r){
		int mid=l+r>>1;
		if(k*s[q[mid]].x+s[q[mid]].y>k*s[q[mid+1]].x+s[q[mid+1]].y)r=mid;
		else l=mid+1;
	}
	if(ab)return k*s[q[l]].x+s[q[l]].y;
	return -3e18;
}
void query(ll l,ll r,ll ab){
	for(int i=l;i<=r;i++)
		if(a[s[i].id]==3)
			ans[s[i].id]=max(ans[s[i].id],gg(ki[s[i].id],ab));
}
void gao(ll l,ll r){
	if(l==r)return ;
	int mid=l+r>>1;
	gao(l,mid),gao(mid+1,r);
	sort(s+l,s+mid+1);
	int ab=0;
	for(int i=l;i<=mid;i++){
		if(a[s[i].id]!=1 or ed[s[i].id]<=r)continue;
		while(ab>1 and(s[i].y-s[q[ab]].y)*(s[i].x-s[q[ab-1]].x)>=(s[i].x-s[q[ab]].x)*(s[i].y-s[q[ab-1]].y))
			ab--;
		q[++ab]=i;
	}
	query(mid+1,r,ab);
	sort(s+mid+1,s+r+1);
	ab=0;
	for(int i=mid+1;i<=r;i++){
		if(a[s[i].id]!=2 or st[s[i].id]>=l)continue;
		while(ab>1 and(s[i].y-s[q[ab]].y)*(s[i].x-s[q[ab-1]].x)>=(s[i].x-s[q[ab]].x)*(s[i].y-s[q[ab-1]].y))
			ab--;
		q[++ab]=i;
	}
	query(l,mid,ab);
}
int main(){
	n=read();
	for(int i=1;i<=n;i++){
		ans[i]=-3e18,a[i]=read(),s[i].id=i;
		if(a[i]==1){
			s[i].x=read(),s[i].y=read();
			ed[i]=n+1;
		}
		else if(a[i]==3)ki[i]=read();
		else{
			int x=read();
			s[i].x=s[x].x;
			s[i].y=s[x].y;
			ed[x]=i,st[i]=x;
		}
	}
	gao(1,n);
	for(int i=1;i<=n;i++)
		if(a[i]==3){
			if(ans[i]<-1e18)puts("EMPTY SET");
			else printf("%lld\n",ans[i]);
		}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
ll read(){
	ll a=0,b=getchar(),c=1;
	while(!isdigit(b))c=b=='-'?-1:1,b=getchar();
	while(isdigit(b))a=a*10+b-'0',b=getchar();
	return a*c;
}
const int M=1e5+5;
struct node{
	ll x,y,id;
	bool operator <(const node &A)const{
		if(x!=A.x)return x<A.x;
		return y<A.y;
	}
}s[M];
ll n,a[M],q[M],ki[M],st[M],ed[M],ans[M];
ll gg(ll k,ll ab){
	int l=1,r=ab;
	while(l<r){
		int mid=l+r>>1;
		if(k*s[q[mid]].x+s[q[mid]].y>k*s[q[mid+1]].x+s[q[mid+1]].y)r=mid;
		else l=mid+1;
	}
	if(ab)return k*s[q[l]].x+s[q[l]].y;
	return -3e18;
}
void query(ll l,ll r,ll ab){
	for(int i=l;i<=r;i++)
		if(a[s[i].id]==3)
			ans[s[i].id]=max(ans[s[i].id],gg(ki[s[i].id],ab));
}
void gao(ll l,ll r){
	if(l==r)return ;
	int mid=l+r>>1;
	gao(l,mid),gao(mid+1,r);
	sort(s+l,s+mid+1);
	int ab=0;
	for(int i=l;i<=mid;i++){
		if(a[s[i].id]!=1 or ed[s[i].id]<=r)continue;
		while(ab>1 and(s[i].y-s[q[ab]].y)*(s[i].x-s[q[ab-1]].x)>=(s[i].x-s[q[ab]].x)*(s[i].y-s[q[ab-1]].y))
			ab--;
		q[++ab]=i;
	}
	query(mid+1,r,ab);
	sort(s+mid+1,s+r+1);
	ab=0;
	for(int i=mid+1;i<=r;i++){
		if(a[s[i].id]!=2 or st[s[i].id]>=l)continue;
		while(ab>1 and(s[i].y-s[q[ab]].y)*(s[i].x-s[q[ab-1]].x)>=(s[i].x-s[q[ab]].x)*(s[i].y-s[q[ab-1]].y))
			ab--;
		q[++ab]=i;
	}
	query(l,mid,ab);
}
int main(){
	n=read();
	for(int i=1;i<=n;i++){
		ans[i]=-3e18,a[i]=read(),s[i].id=i;
		if(a[i]==1){
			s[i].x=read(),s[i].y=read();
			ed[i]=n+1;
		}
		else if(a[i]==3)ki[i]=read();
		else{
			int x=read();
			s[i].x=s[x].x;
			s[i].y=s[x].y;
			ed[x]=i,st[i]=x;
		}
	}
	gao(1,n);
	for(int i=1;i<=n;i++)
		if(a[i]==3){
			if(ans[i]<-1e18)puts("EMPTY SET");
			else printf("%lld\n",ans[i]);
		}
	return 0;
}