#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 300010;
const ll INF = 2e18;

int t[maxn];
ll a[maxn];
ll b[maxn];
bool ban[maxn];
ll ans[maxn];
ll ans2[maxn];

struct Point{
	ll x,y;
	Point(ll x,ll y):x(x),y(y){
	}
	Point(){
	}

	bool operator<(const Point &other)const{
		if(x!=other.x){
			return x<other.x;
		}
		return y>other.y;
	}
};

//Point pts[maxn];
multiset<Point> pts;
Point ch[maxn];

int sz;

void ConvexHull(){
	int k = 0;
	/*
	for(int i=1;i<=n;i++){
		if(t[i]==1 && !ban[i]){
			pts[k++] = Point(a[i],b[i]);
		}
	}
	sort(pts,pts+k);
	*/
	sz = 0;
	for(auto pt:pts){
		if(sz<2){
			ch[sz++] = pt;
		}else{
			while(sz>=2 && (pt.y-ch[sz-1].y)*(ch[sz-1].x-ch[sz-2].x) >=
					(ch[sz-1].y-ch[sz-2].y)*(pt.x-ch[sz-1].x) ){
				sz--;
			}
			ch[sz++] = pt;
		}
	}
}

int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&t[i]);
		if(t[i] == 1){
			scanf("%I64d%I64d",&a[i],&b[i]);
		}else{
			scanf("%I64d",&a[i]);
		}
		ans[i] = -INF;
		ans2[i] = -INF;
	}

	int LEN = sqrt(n);
	Point pt_in_block[555];
	pair<ll,int> query_in_block[555];
	int cntq = 0;
	int k = 0;
	for(int s=1;s<=n;s+=LEN){
		int e = min(n+1,s+LEN);
		cntq = 0;
		//cout<<"handle segment "<<s<<" "<<e<<endl;
		for(int i=s;i<e;i++){
			//cout<<"--calc "<<i<<endl;
			if(t[i] == 3){
				for(int j=s;j<e;j++){
					if(t[j] == 1 && j < i && !ban[j]){
						ans[i] = max(ans[i],b[j]+a[j]*a[i]);
					}else if(t[j] == 2 && j > i && a[j] < i){
						int aa = a[a[j]];
						int bb = b[a[j]];
						ans[i] = max(ans[i],bb+aa*a[i]);
					}
				}
				query_in_block[cntq++] = make_pair(a[i],i);
			}else if(t[i] == 2){
				ban[a[i]] = 1;
			}
		}

		sort(query_in_block,query_in_block+cntq);
		ConvexHull();
		if(sz == 0){	//empty set
			continue;
		}else{
			int pos = 0;
			for(int i=0;i<cntq;i++){
				while(pos<sz){
					ll val = ch[pos].y + query_in_block[i].first*ch[pos].x;
					if( val > ans2[query_in_block[i].second]){
						ans2[query_in_block[i].second] = val;
					//	cout<<"modify "<<query_in_block[i].second<<endl;
					}else{
						if(pos){
							pos--;
						}
						break;
					}

					pos++;
					if(pos==sz){
						if(pos)pos--;
						break;
					}
				}
			}
		}
		for(int i=s;i<e;i++){
			if(t[i] == 1 && !ban[i]){
				pts.insert(Point(a[i],b[i]));
			}else if(t[i] == 2){
				pts.erase(Point(a[a[i]],a[a[i]]));
			}
		}
	}

	for(int i=1;i<=n;i++){
		if(t[i] == 3){
			ll a = max(ans[i],ans2[i]);
			if(a == -INF){
				printf("EMPTY SET\n");
			}else{
				printf("%I64d\n",a);
			}
		}
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 300010;
const ll INF = 2e18;

int t[maxn];
ll a[maxn];
ll b[maxn];
bool ban[maxn];
ll ans[maxn];

struct Point{
	int x,y;
	Point(int x,int y):x(x),y(y){
	}
	Point(){
	}

	bool operator<(const Point &other)const{
		if(x!=other.x){
			return x<other.x;
		}
		return y>other.y;
	}
};

Point pts[maxn];
Point ch[maxn];

int sz;

void ConvexHull(int n){
	int k = 0;
	for(int i=1;i<=n;i++){
		if(t[i]==1 && !ban[i]){
			pts[k++] = Point(a[i],b[i]);
		}
	}
	sort(pts,pts+k);
	sz = 0;
	for(int i=0;i<k;i++){
		if(i && pts[i].x == pts[i-1].x){
			continue;
		}
		if(sz<2){
			ch[sz++] = pts[i];
		}else{
			while(sz>=2 && (pts[i].y-ch[sz-1].y)*(ch[sz-1].x-ch[sz-2].x) >
					(ch[sz-1].y-ch[sz-2].y)*(pts[i].x-ch[sz-1].x) ){
				sz--;
			}
			ch[sz++] = pts[i];
		}
	}
}

int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&t[i]);
		if(t[i] == 1){
			scanf("%I64d%I64d",&a[i],&b[i]);
		}else{
			scanf("%I64d",&a[i]);
		}
		ans[i] = -INF;
	}

	int LEN = sqrt(n);
	Point pt_in_block[555];
	pair<ll,int> query_in_block[555];
	int cntq = 0;
	int k = 0;
	for(int s=1;s<=n;s+=LEN){
		int e = min(n+1,s+LEN);
		cntq = 0;
		//cout<<"handle segment "<<s<<" "<<e<<endl;
		for(int i=s;i<e;i++){
		//	cout<<"--calc "<<i<<endl;
			if(t[i] == 3){
				for(int j=s;j<e;j++){
					if(t[j] == 1 && j < i){
						ans[i] = max(ans[i],b[i]+a[i]*a[j]);
					//	cout<<"?";
					}else if(t[j] == 2 && j > i && a[j] < i && !ban[j]){
						int aa = a[a[j]];
						int bb = b[a[j]];
						ans[i] = max(ans[i],bb+aa*a[i]);
					//	cout<<"?";
					}
				}
				query_in_block[cntq++] = make_pair(a[i],i);
			}else if(t[i] == 2){
				ban[a[i]] = 1;
			}
		}

		sort(query_in_block,query_in_block+cntq);
		ConvexHull(s-1);
		if(sz == 0){	//empty set
			continue;
		}else{
			int pos = 0;
			for(int i=0;i<cntq;i++){
				while(pos<sz){
					ll val = ch[pos].y + query_in_block[i].first*ch[pos].x;
					if( val > ans[query_in_block[i].second]){
						ans[query_in_block[i].second] = val;
					//	cout<<"modify "<<query_in_block[i].second<<endl;
					}else{
						if(pos){
							pos--;
						}
						break;
					}

					pos++;
					if(pos==sz){
						if(pos)pos--;
						break;
					}
				}
			}
		}
	}

	for(int i=1;i<=n;i++){
		if(t[i] == 3){
			if(ans[i] == -INF){
				printf("EMPTY SET\n");
			}else{
				printf("%I64d\n",ans[i]);
			}
		}
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 300010;
const ll INF = 2e18;

int t[maxn];
ll a[maxn];
ll b[maxn];
bool ban[maxn];
ll ans[maxn];

struct Point{
	int x,y;
	Point(int x,int y):x(x),y(y){
	}
	Point(){
	}

	bool operator<(const Point &other)const{
		if(x!=other.x){
			return x<other.x;
		}
		return y>other.y;
	}
};

Point pts[maxn];
Point ch[maxn];

int sz;

void ConvexHull(int n){
	int k = 0;
	for(int i=1;i<=n;i++){
		if(t[i]==1 && !ban[i]){
			pts[k++] = Point(a[i],b[i]);
		}
	}
	sort(pts,pts+k);
	sz = 0;
	for(int i=0;i<k;i++){
		if(i && pts[i].x == pts[i-1].x){
			continue;
		}
		if(sz<2){
			ch[sz++] = pts[i];
		}else{
			while(sz>=2 && (pts[i].y-ch[sz-1].y)*(ch[sz-1].x-ch[sz-2].x) >
					(ch[sz-1].y-ch[sz-2].y)*(pts[i].x-ch[sz-1].x) ){
				sz--;
			}
			ch[sz++] = pts[i];
		}
	}
}

int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&t[i]);
		if(t[i] == 1){
			scanf("%I64d%I64d",&a[i],&b[i]);
		}else{
			scanf("%I64d",&a[i]);
		}
		ans[i] = -INF;
	}

	int LEN = sqrt(n);
	Point pt_in_block[555];
	pair<ll,int> query_in_block[555];
	int cntq = 0;
	int k = 0;
	for(int s=1;s<=n;s+=LEN){
		int e = min(n+1,s+LEN);
		cntq = 0;
	//	cout<<"handle segment "<<s<<" "<<e<<endl;
		for(int i=s;i<e;i++){
		//	cout<<"--calc "<<i<<endl;
			if(t[i] == 3){
				for(int j=s;j<e;j++){
					if(t[j] == 1 && j < i){
						ans[i] = max(ans[i],b[i]+a[i]*a[j]);
					//	cout<<"?";
					}else if(t[j] == 2 && j > i){
						int aa = a[a[j]];
						int bb = b[a[j]];
						ans[i] = max(ans[i],bb+aa*a[i]);
					//	cout<<"?";
					}
				}
				query_in_block[cntq++] = make_pair(a[i],i);
			}else if(t[i] == 2){
				ban[a[i]] = 1;
			}
		}

		sort(query_in_block,query_in_block+cntq);
		ConvexHull(s-1);
		if(sz == 0){	//empty set
			continue;
		}else{
			int pos = 0;
			for(int i=0;i<cntq;i++){
				while(pos<sz){
					ll val = ch[pos].y + query_in_block[i].first*ch[pos].x;
					if( val > ans[query_in_block[i].second]){
						ans[query_in_block[i].second] = val;
					//	cout<<"modify "<<query_in_block[i].second<<endl;
					}else{
						if(pos){
							pos--;
						}
						break;
					}

					pos++;
					if(pos==sz){
						if(pos)pos--;
						break;
					}
				}
			}
		}
	}

	for(int i=1;i<=n;i++){
		if(t[i] == 3){
			if(ans[i] == -INF){
				printf("EMPTY SET\n");
			}else{
				printf("%I64d\n",ans[i]);
			}
		}
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 300010;
const ll INF = 2e18;

int t[maxn];
ll a[maxn];
ll b[maxn];
bool ban[maxn];
ll ans[maxn];
ll ans2[maxn];

struct Point{
	ll x,y;
	Point(ll x,ll y):x(x),y(y){
	}
	Point(){
	}

	bool operator<(const Point &other)const{
		if(x!=other.x){
			return x<other.x;
		}
		return y>other.y;
	}
};

//Point pts[maxn];
set<Point> pts;
Point ch[maxn];

int sz;

void ConvexHull(){
	int k = 0;
	/*
	for(int i=1;i<=n;i++){
		if(t[i]==1 && !ban[i]){
			pts[k++] = Point(a[i],b[i]);
		}
	}
	sort(pts,pts+k);
	*/
	sz = 0;
	Point pre = Point(-INF,-INF);
	for(auto pt:pts){
		if(pt.x == pre.x){
			continue;
		}
		pre = pt;
		if(sz<2){
			ch[sz++] = pt;
		}else{
			while(sz>=2 && (pt.y-ch[sz-1].y)*(ch[sz-1].x-ch[sz-2].x) >=
					(ch[sz-1].y-ch[sz-2].y)*(pt.x-ch[sz-1].x) ){
				sz--;
			}
			ch[sz++] = pt;
		}
	}
}

int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&t[i]);
		if(t[i] == 1){
			scanf("%I64d%I64d",&a[i],&b[i]);
		}else{
			scanf("%I64d",&a[i]);
		}
		ans[i] = -INF;
		ans2[i] = -INF;
	}

	int LEN = sqrt(n);
	Point pt_in_block[555];
	pair<ll,int> query_in_block[555];
	int cntq = 0;
	int k = 0;
	for(int s=1;s<=n;s+=LEN){
		int e = min(n+1,s+LEN);
		cntq = 0;
		//cout<<"handle segment "<<s<<" "<<e<<endl;
		for(int i=s;i<e;i++){
			//cout<<"--calc "<<i<<endl;
			if(t[i] == 3){
				for(int j=s;j<e;j++){
					if(t[j] == 1 && j < i && !ban[j]){
						ans[i] = max(ans[i],b[j]+a[j]*a[i]);
					}else if(t[j] == 2 && j > i && a[j] < i){
						int aa = a[a[j]];
						int bb = b[a[j]];
						ans[i] = max(ans[i],bb+aa*a[i]);
					}
				}
				query_in_block[cntq++] = make_pair(a[i],i);
			}else if(t[i] == 2){
				ban[a[i]] = 1;
				pts.erase(Point(a[a[i]],b[a[i]]));
			}
		}

		sort(query_in_block,query_in_block+cntq);
		ConvexHull();
		if(sz != 0){
			int pos = 0;
			for(int i=0;i<cntq;i++){
				while(pos<sz){
					ll val = ch[pos].y + query_in_block[i].first*ch[pos].x;
					if( val > ans2[query_in_block[i].second]){
						ans2[query_in_block[i].second] = val;
					//	cout<<"modify "<<query_in_block[i].second<<endl;
					}else{
						if(pos){
							pos--;
						}
						break;
					}

					pos++;
					if(pos==sz){
						if(pos)pos--;
						break;
					}
				}
			}
		}
		for(int i=s;i<e;i++){
			if(t[i] == 1 && !ban[i]){
				pts.insert(Point(a[i],b[i]));
			}
		}
	}

	for(int i=1;i<=n;i++){
		if(t[i] == 3){
			ll a = max(ans[i],ans2[i]);
			if(a == -INF){
				printf("EMPTY SET\n");
			}else{
				printf("%I64d\n",a);
			}
		}
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 300010;
const ll INF = 2e18;

int t[maxn];
ll a[maxn];
ll b[maxn];
bool ban[maxn];
ll ans[maxn];
ll ans2[maxn];

struct Point{
	int x,y;
	Point(int x,int y):x(x),y(y){
	}
	Point(){
	}

	bool operator<(const Point &other)const{
		if(x!=other.x){
			return x<other.x;
		}
		return y>other.y;
	}
};

Point pts[maxn];
Point ch[maxn];

int sz;

void ConvexHull(int n){
	int k = 0;
	for(int i=1;i<=n;i++){
		if(t[i]==1 && !ban[i]){
			pts[k++] = Point(a[i],b[i]);
		}
	}
	sort(pts,pts+k);
	sz = 0;
	for(int i=0;i<k;i++){
		if(i && pts[i].x == pts[i-1].x){
			continue;
		}
		if(sz<2){
			ch[sz++] = pts[i];
		}else{
			while(sz>=2 && (pts[i].y-ch[sz-1].y)*(ch[sz-1].x-ch[sz-2].x) >=
					(ch[sz-1].y-ch[sz-2].y)*(pts[i].x-ch[sz-1].x) ){
				sz--;
			}
			ch[sz++] = pts[i];
		}
	}
}

int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&t[i]);
		if(t[i] == 1){
			scanf("%I64d%I64d",&a[i],&b[i]);
		}else{
			scanf("%I64d",&a[i]);
		}
		ans[i] = -INF;
		ans2[i] = -INF;
	}

	int LEN = sqrt(n);
	Point pt_in_block[555];
	pair<ll,int> query_in_block[555];
	int cntq = 0;
	int k = 0;
	for(int s=1;s<=n;s+=LEN){
		int e = min(n+1,s+LEN);
		cntq = 0;
		//cout<<"handle segment "<<s<<" "<<e<<endl;
		for(int i=s;i<e;i++){
			//cout<<"--calc "<<i<<endl;
			if(t[i] == 3){
				for(int j=s;j<e;j++){
					if(t[j] == 1 && j < i && !ban[j]){
						ans[i] = max(ans[i],b[j]+a[j]*a[i]);
					}else if(t[j] == 2 && j > i && a[j] < i){
						int aa = a[a[j]];
						int bb = b[a[j]];
						ans[i] = max(ans[i],bb+aa*a[i]);
					}
				}
				query_in_block[cntq++] = make_pair(a[i],i);
			}else if(t[i] == 2){
				ban[a[i]] = 1;
			}
		}

		sort(query_in_block,query_in_block+cntq);
		ConvexHull(s-1);
		if(sz == 0){	//empty set
			continue;
		}else{
			int pos = 0;
			for(int i=0;i<cntq;i++){
				while(pos<sz){
					ll val = ch[pos].y + query_in_block[i].first*ch[pos].x;
					if( val > ans2[query_in_block[i].second]){
						ans2[query_in_block[i].second] = val;
					//	cout<<"modify "<<query_in_block[i].second<<endl;
					}else{
						if(pos){
							pos--;
						}
						break;
					}

					pos++;
					if(pos==sz){
						if(pos)pos--;
						break;
					}
				}
			}
		}
	}

	for(int i=1;i<=n;i++){
		if(t[i] == 3){
			int a = max(ans[i],ans2[i]);
			if(a == -INF){
				printf("EMPTY SET\n");
			}else{
				printf("%I64d\n",a);
			}
		}
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 300010;
const ll INF = 2e18;

int t[maxn];
ll a[maxn];
ll b[maxn];
bool ban[maxn];
ll ans[maxn];
ll ans2[maxn];

struct Point{
	ll x,y;
	Point(ll x,ll y):x(x),y(y){
	}
	Point(){
	}

	bool operator<(const Point &other)const{
		if(x!=other.x){
			return x<other.x;
		}
		return y>other.y;
	}
};

Point pts[maxn];
Point ch[maxn];

int sz;

void ConvexHull(int n){
	int k = 0;
	for(int i=1;i<=n;i++){
		if(t[i]==1 && !ban[i]){
			pts[k++] = Point(a[i],b[i]);
		}
	}
	sort(pts,pts+k);
	sz = 0;
	for(int i=0;i<k;i++){
		if(i && pts[i].x == pts[i-1].x){
			continue;
		}
		if(sz<2){
			ch[sz++] = pts[i];
		}else{
			while(sz>=2 && (pts[i].y-ch[sz-1].y)*(ch[sz-1].x-ch[sz-2].x) >=
					(ch[sz-1].y-ch[sz-2].y)*(pts[i].x-ch[sz-1].x) ){
				sz--;
			}
			ch[sz++] = pts[i];
		}
	}
}

int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&t[i]);
		if(t[i] == 1){
			scanf("%I64d%I64d",&a[i],&b[i]);
		}else{
			scanf("%I64d",&a[i]);
		}
		ans[i] = -INF;
		ans2[i] = -INF;
	}

	int LEN = sqrt(n);
	Point pt_in_block[555];
	pair<ll,int> query_in_block[555];
	int cntq = 0;
	int k = 0;
	for(int s=1;s<=n;s+=LEN){
		int e = min(n+1,s+LEN);
		cntq = 0;
		//cout<<"handle segment "<<s<<" "<<e<<endl;
		for(int i=s;i<e;i++){
			//cout<<"--calc "<<i<<endl;
			if(t[i] == 3){
				for(int j=s;j<e;j++){
					if(t[j] == 1 && j < i && !ban[j]){
						ans[i] = max(ans[i],b[j]+a[j]*a[i]);
					}else if(t[j] == 2 && j > i && a[j] < i){
						int aa = a[a[j]];
						int bb = b[a[j]];
						ans[i] = max(ans[i],bb+aa*a[i]);
					}
				}
				query_in_block[cntq++] = make_pair(a[i],i);
			}else if(t[i] == 2){
				ban[a[i]] = 1;
			}
		}

		sort(query_in_block,query_in_block+cntq);
		ConvexHull(s-1);
		if(sz == 0){	//empty set
			continue;
		}else{
			int pos = 0;
			for(int i=0;i<cntq;i++){
				while(pos<sz){
					ll val = ch[pos].y + query_in_block[i].first*ch[pos].x;
					if( val > ans2[query_in_block[i].second]){
						ans2[query_in_block[i].second] = val;
					//	cout<<"modify "<<query_in_block[i].second<<endl;
					}else{
						if(pos){
							pos--;
						}
						break;
					}

					pos++;
					if(pos==sz){
						if(pos)pos--;
						break;
					}
				}
			}
		}
	}

	for(int i=1;i<=n;i++){
		if(t[i] == 3){
			ll a = max(ans[i],ans2[i]);
			if(a == -INF){
				printf("EMPTY SET\n");
			}else{
				printf("%I64d\n",a);
			}
		}
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 300010;
const ll INF = 2e18;

int t[maxn];
ll a[maxn];
ll b[maxn];
bool ban[maxn];
ll ans[maxn];
ll ans2[maxn];

struct Point{
	ll x,y;
	Point(ll x,ll y):x(x),y(y){
	}
	Point(){
	}

	bool operator<(const Point &other)const{
		if(x!=other.x){
			return x<other.x;
		}
		return y>other.y;
	}
};

//Point pts[maxn];
multiset<Point> pts;
Point ch[maxn];

int sz;

void ConvexHull(){
	int k = 0;
	/*
	for(int i=1;i<=n;i++){
		if(t[i]==1 && !ban[i]){
			pts[k++] = Point(a[i],b[i]);
		}
	}
	sort(pts,pts+k);
	*/
	sz = 0;
	for(auto pt:pts){
		if(sz<2){
			ch[sz++] = pt;
		}else{
			while(sz>=2 && (pt.y-ch[sz-1].y)*(ch[sz-1].x-ch[sz-2].x) >=
					(ch[sz-1].y-ch[sz-2].y)*(pt.x-ch[sz-1].x) ){
				sz--;
			}
			ch[sz++] = pt;
		}
	}
}

int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&t[i]);
		if(t[i] == 1){
			scanf("%I64d%I64d",&a[i],&b[i]);
		}else{
			scanf("%I64d",&a[i]);
		}
		ans[i] = -INF;
		ans2[i] = -INF;
	}

	int LEN = sqrt(n);
	Point pt_in_block[555];
	pair<ll,int> query_in_block[555];
	int cntq = 0;
	int k = 0;
	for(int s=1;s<=n;s+=LEN){
		int e = min(n+1,s+LEN);
		cntq = 0;
		//cout<<"handle segment "<<s<<" "<<e<<endl;
		for(int i=s;i<e;i++){
			//cout<<"--calc "<<i<<endl;
			if(t[i] == 3){
				for(int j=s;j<e;j++){
					if(t[j] == 1 && j < i && !ban[j]){
						ans[i] = max(ans[i],b[j]+a[j]*a[i]);
					}else if(t[j] == 2 && j > i && a[j] < i){
						int aa = a[a[j]];
						int bb = b[a[j]];
						ans[i] = max(ans[i],bb+aa*a[i]);
					}
				}
				query_in_block[cntq++] = make_pair(a[i],i);
			}else if(t[i] == 2){
				ban[a[i]] = 1;
			}
		}

		sort(query_in_block,query_in_block+cntq);
		ConvexHull();
		if(sz != 0){
			int pos = 0;
			for(int i=0;i<cntq;i++){
				while(pos<sz){
					ll val = ch[pos].y + query_in_block[i].first*ch[pos].x;
					if( val > ans2[query_in_block[i].second]){
						ans2[query_in_block[i].second] = val;
					//	cout<<"modify "<<query_in_block[i].second<<endl;
					}else{
						if(pos){
							pos--;
						}
						break;
					}

					pos++;
					if(pos==sz){
						if(pos)pos--;
						break;
					}
				}
			}
		}
		for(int i=s;i<e;i++){
			if(t[i] == 1 && !ban[i]){
				pts.insert(Point(a[i],b[i]));
			}else if(t[i] == 2){
				pts.erase(Point(a[a[i]],b[a[i]]));
			}
		}
	}

	for(int i=1;i<=n;i++){
		if(t[i] == 3){
			ll a = max(ans[i],ans2[i]);
			if(a == -INF){
				printf("EMPTY SET\n");
			}else{
				printf("%I64d\n",a);
			}
		}
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 300010;
const ll INF = 2e18;

int t[maxn];
ll a[maxn];
ll b[maxn];
bool ban[maxn];
ll ans[maxn];

struct Point{
	int x,y;
	Point(int x,int y):x(x),y(y){
	}
	Point(){
	}

	bool operator<(const Point &other)const{
		if(x!=other.x){
			return x<other.x;
		}
		return y>other.y;
	}
};

Point pts[maxn];
Point ch[maxn];

int sz;

void ConvexHull(int n){
	int k = 0;
	for(int i=1;i<=n;i++){
		if(t[i]==1 && !ban[i]){
			pts[k++] = Point(a[i],b[i]);
		}
	}
	sort(pts,pts+k);
	sz = 0;
	for(int i=0;i<k;i++){
		if(i && pts[i].x == pts[i-1].x){
			continue;
		}
		if(sz<2){
			ch[sz++] = pts[i];
		}else{
			while(sz>=2 && (pts[i].y-ch[sz-1].y)*(ch[sz-1].x-ch[sz-2].x) >
					(ch[sz-1].y-ch[sz-2].y)*(pts[i].x-ch[sz-1].x) ){
				sz--;
			}
			ch[sz++] = pts[i];
		}
	}
}

int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&t[i]);
		if(t[i] == 1){
			scanf("%I64d%I64d",&a[i],&b[i]);
		}else{
			scanf("%I64d",&a[i]);
		}
		ans[i] = -INF;
	}

	int LEN = sqrt(n);
	Point pt_in_block[555];
	pair<ll,int> query_in_block[555];
	int cntq = 0;
	int k = 0;
	for(int s=1;s<=n;s+=LEN){
		int e = min(n+1,s+LEN);
		cntq = 0;
		//cout<<"handle segment "<<s<<" "<<e<<endl;
		for(int i=s;i<e;i++){
			//cout<<"--calc "<<i<<endl;
			if(t[i] == 3){
				for(int j=s;j<e;j++){
					if(t[j] == 1 && j < i && !ban[j]){
						ans[i] = max(ans[i],b[i]+a[i]*a[j]);
					}else if(t[j] == 2 && j > i && a[j] < i){
						int aa = a[a[j]];
						int bb = b[a[j]];
						ans[i] = max(ans[i],bb+aa*a[i]);
					}
				}
				query_in_block[cntq++] = make_pair(a[i],i);
			}else if(t[i] == 2){
				ban[a[i]] = 1;
			}
		}

		sort(query_in_block,query_in_block+cntq);
		ConvexHull(s-1);
		if(sz == 0){	//empty set
			continue;
		}else{
			int pos = 0;
			for(int i=0;i<cntq;i++){
				while(pos<sz){
					ll val = ch[pos].y + query_in_block[i].first*ch[pos].x;
					if( val > ans[query_in_block[i].second]){
						ans[query_in_block[i].second] = val;
					//	cout<<"modify "<<query_in_block[i].second<<endl;
					}else{
						if(pos){
							pos--;
						}
						break;
					}

					pos++;
					if(pos==sz){
						if(pos)pos--;
						break;
					}
				}
			}
		}
	}

	for(int i=1;i<=n;i++){
		if(t[i] == 3){
			if(ans[i] == -INF){
				printf("EMPTY SET\n");
			}else{
				printf("%I64d\n",ans[i]);
			}
		}
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 300010;
const ll INF = 2e18;

int t[maxn];
ll a[maxn];
ll b[maxn];
bool ban[maxn];
ll ans[maxn];
ll ans2[maxn];

struct Point{
	ll x,y;
	Point(ll x,ll y):x(x),y(y){
	}
	Point(){
	}

	bool operator<(const Point &other)const{
		if(x!=other.x){
			return x<other.x;
		}
		return y>other.y;
	}
};

//Point pts[maxn];
Point ch[maxn];
pair<Point,int> ppi[maxn];

int sz;

int n;
int k;

void ConvexHull(int end){
	sz = 0;
	Point pre = Point(-INF,-INF);
	for(int i=0;i<k;i++){
		Point pt = ppi[i].first;
		if(ban[ppi[i].second] || ppi[i].second>end ){
			continue;
		}
		if(pt.x == pre.x){
			continue;
		}
		pre = pt;
		if(sz<2){
			ch[sz++] = pt;
		}else{
			while(sz>=2 && (pt.y-ch[sz-1].y)*(ch[sz-1].x-ch[sz-2].x) >=
					(ch[sz-1].y-ch[sz-2].y)*(pt.x-ch[sz-1].x) ){
				sz--;
			}
			ch[sz++] = pt;
		}
	}
}

int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&t[i]);
		if(t[i] == 1){
			scanf("%I64d%I64d",&a[i],&b[i]);
			ppi[k++] = make_pair(Point(a[i],b[i]),i);
		}else{
			scanf("%I64d",&a[i]);
		}
		ans[i] = ans2[i] = -INF;
	}

	sort(ppi,ppi+k);

	int LEN = sqrt(n);
	Point pt_in_block[555];
	pair<ll,int> query_in_block[555];
	int cntq = 0;
	int k = 0;
	for(int s=1;s<=n;s+=LEN){
		int e = min(n+1,s+LEN);
		cntq = 0;
		//cout<<"handle segment "<<s<<" "<<e<<endl;
		for(int i=s;i<e;i++){
			//cout<<"--calc "<<i<<endl;
			if(t[i] == 3){
				for(int j=s;j<e;j++){
					if(t[j] == 1 && j < i && !ban[j]){
						ans[i] = max(ans[i],b[j]+a[j]*a[i]);
					}else if(t[j] == 2 && j > i && a[j] < i){
						int aa = a[a[j]];
						int bb = b[a[j]];
						ans[i] = max(ans[i],bb+aa*a[i]);
					}
				}
				query_in_block[cntq++] = make_pair(a[i],i);
			}else if(t[i] == 2){
				ban[a[i]] = 1;
			}
		}

		sort(query_in_block,query_in_block+cntq);
		ConvexHull(s-1);
		if(sz != 0){
			int pos = 0;
			for(int i=0;i<cntq;i++){
				while(pos<sz){
					ll val = ch[pos].y + query_in_block[i].first*ch[pos].x;
					if( val > ans2[query_in_block[i].second]){
						ans2[query_in_block[i].second] = val;
					//	cout<<"modify "<<query_in_block[i].second<<endl;
					}else{
						if(pos){
							pos--;
						}
						break;
					}

					pos++;
					if(pos==sz){
						if(pos)pos--;
						break;
					}
				}
			}
		}
	}

	for(int i=1;i<=n;i++){
		if(t[i] == 3){
			ll a = max(ans[i],ans2[i]);
			if(a == -INF){
				printf("EMPTY SET\n");
			}else{
				printf("%I64d\n",a);
			}
		}
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 300010;
const ll INF = 2e18;

int t[maxn];
ll a[maxn];
ll b[maxn];
bool ban[maxn];
ll ans[maxn];
ll ans2[maxn];

struct Point{
	ll x,y;
	Point(ll x,ll y):x(x),y(y){
	}
	Point(){
	}

	bool operator<(const Point &other)const{
		if(x!=other.x){
			return x<other.x;
		}
		return y>other.y;
	}
};

//Point pts[maxn];
multiset<Point> pts;
Point ch[maxn];

int sz;

void ConvexHull(){
	int k = 0;
	/*
	for(int i=1;i<=n;i++){
		if(t[i]==1 && !ban[i]){
			pts[k++] = Point(a[i],b[i]);
		}
	}
	sort(pts,pts+k);
	*/
	sz = 0;
	for(auto pt:pts){
		if(sz<2){
			ch[sz++] = pt;
		}else{
			while(sz>=2 && (pt.y-ch[sz-1].y)*(ch[sz-1].x-ch[sz-2].x) >=
					(ch[sz-1].y-ch[sz-2].y)*(pt.x-ch[sz-1].x) ){
				sz--;
			}
			ch[sz++] = pt;
		}
	}
}

int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&t[i]);
		if(t[i] == 1){
			scanf("%I64d%I64d",&a[i],&b[i]);
		}else{
			scanf("%I64d",&a[i]);
		}
		ans[i] = -INF;
		ans2[i] = -INF;
	}

	int LEN = sqrt(n);
	Point pt_in_block[555];
	pair<ll,int> query_in_block[555];
	int cntq = 0;
	int k = 0;
	for(int s=1;s<=n;s+=LEN){
		int e = min(n+1,s+LEN);
		cntq = 0;
		//cout<<"handle segment "<<s<<" "<<e<<endl;
		for(int i=s;i<e;i++){
			//cout<<"--calc "<<i<<endl;
			if(t[i] == 3){
				for(int j=s;j<e;j++){
					if(t[j] == 1 && j < i && !ban[j]){
						ans[i] = max(ans[i],b[j]+a[j]*a[i]);
					}else if(t[j] == 2 && j > i && a[j] < i){
						int aa = a[a[j]];
						int bb = b[a[j]];
						ans[i] = max(ans[i],bb+aa*a[i]);
					}
				}
				query_in_block[cntq++] = make_pair(a[i],i);
			}else if(t[i] == 2){
				ban[a[i]] = 1;
			}
		}

		sort(query_in_block,query_in_block+cntq);
		ConvexHull();
		if(sz != 0){
			int pos = 0;
			for(int i=0;i<cntq;i++){
				while(pos<sz){
					ll val = ch[pos].y + query_in_block[i].first*ch[pos].x;
					if( val > ans2[query_in_block[i].second]){
						ans2[query_in_block[i].second] = val;
					//	cout<<"modify "<<query_in_block[i].second<<endl;
					}else{
						if(pos){
							pos--;
						}
						break;
					}

					pos++;
					if(pos==sz){
						if(pos)pos--;
						break;
					}
				}
			}
		}
		for(int i=s;i<e;i++){
			if(t[i] == 1 ){
				pts.insert(Point(a[i],b[i]));
			}else if(t[i] == 2){
				pts.erase(Point(a[a[i]],b[a[i]]));
			}
		}
	}

	for(int i=1;i<=n;i++){
		if(t[i] == 3){
			ll a = max(ans[i],ans2[i]);
			if(a == -INF){
				printf("EMPTY SET\n");
			}else{
				printf("%I64d\n",a);
			}
		}
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 300010;
const ll INF = 2e18;

int t[maxn];
ll a[maxn];
ll b[maxn];
ll ans[maxn];
int r[maxn];

inline int getID(int l,int r){
	return (l+r)|(l<r);
}

struct Point{
	ll x,y;
	Point(ll x,ll y):x(x),y(y){
	}
	Point(){
	}
	bool operator<(const Point &other)const{
		if(x!=other.x){
			return x<other.x;
		}
		return y>other.y;
	}
};

Point ch[maxn];
vector<Point> pts[maxn<<1];

void update(int tl,int tr,int l,int r,Point pt){
	if(l == tl && r == tr){
		pts[getID(l,r)].push_back(pt);
		return;
	}
	int mid = (tl+tr)>>1;
	if(r <= mid){
		update(tl,mid,l,r,pt);
	}else{
		if(l > mid){
			update(mid+1,tr,l,r,pt);
		}else{
			update(tl,mid,l,mid,pt);
			update(mid+1,tr,mid+1,r,pt);
		}
	}
}

int sz;	//ConvexHull's size

int n;

void ConvexHull(int id){
	sort(pts[id].begin(),pts[id].end());
	sz = 0;
	Point pre = Point(-INF,-INF);
	for(int i=0;i<(int)pts[id].size();i++){
		Point pt = pts[id][i];
		if(pt.x == pre.x){
			continue;
		}
		pre = pt;
		if(sz<2){
			ch[sz++] = pt;
		}else{
			while(sz>=2 && (pt.y-ch[sz-1].y)*(ch[sz-1].x-ch[sz-2].x) >=
					(ch[sz-1].y-ch[sz-2].y)*(pt.x-ch[sz-1].x) ){
				sz--;
			}
			ch[sz++] = pt;
		}
	}
}

inline ll calc(int ptid,int qid){
	return ch[ptid].y+ch[ptid].x*a[qid];
}

ll bs(int l,int r,int qid){
	int L = l;
	int R = r;
	ll res = -INF;
	while(l<=r){
		int mid = (l+r)>>1;
		ll mval = calc(mid,qid);
		res = max(res,mval);
		if(mid > L && calc(mid-1,qid) > mval){
			r = mid-1;
		}else if(mid < R && calc(mid+1,qid) > mval){
			l = mid+1;
		}else{
			break;
		}
	}
	return res;
}

void cdq(int l,int r){
	int mid = (l+r)>>1;

	if(l<r)cdq(l,mid);
	if(l<r)cdq(mid+1,r);

	ConvexHull(getID(l,r));
	for(int i=l;i<=r;i++){
		if(t[i] == 3){
			ans[i] = max(ans[i],bs(0,sz-1,i));
		}
	}
}

int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&t[i]);
		if(t[i] == 1){
			scanf("%I64d%I64d",&a[i],&b[i]);
			r[i] = n;
		}else{
			scanf("%I64d",&a[i]);
			if(t[i] == 2){
				r[a[i]] = i-1;
			}
		}
		ans[i] = -INF;
	}

	for(int i=1;i<=n;i++){
		if(t[i] == 1){
			if(i+1<=r[i])update(1,n,i+1,r[i],Point(a[i],b[i]));
		}
	}

	cdq(1,n);

	for(int i=1;i<=n;i++){
		if(t[i] == 3){
			if(ans[i] == -INF){
				printf("EMPTY SET\n");
			}else{
				printf("%I64d\n",ans[i]);
			}
		}
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 300010;
const ll INF = 2e18;

int t[maxn];
ll a[maxn];
ll b[maxn];
bool ban[maxn];
ll ans[maxn];
ll ans2[maxn];

struct Point{
	int x,y;
	Point(int x,int y):x(x),y(y){
	}
	Point(){
	}

	bool operator<(const Point &other)const{
		if(x!=other.x){
			return x<other.x;
		}
		return y>other.y;
	}
};

Point pts[maxn];
Point ch[maxn];

int sz;

void ConvexHull(int n){
	int k = 0;
	for(int i=1;i<=n;i++){
		if(t[i]==1 && !ban[i]){
			pts[k++] = Point(a[i],b[i]);
		}
	}
	sort(pts,pts+k);
	sz = 0;
	for(int i=0;i<k;i++){
		if(i && pts[i].x == pts[i-1].x){
			continue;
		}
		if(sz<2){
			ch[sz++] = pts[i];
		}else{
			while(sz>=2 && (pts[i].y-ch[sz-1].y)*(ch[sz-1].x-ch[sz-2].x) >=
					(ch[sz-1].y-ch[sz-2].y)*(pts[i].x-ch[sz-1].x) ){
				sz--;
			}
			ch[sz++] = pts[i];
		}
	}
}

int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&t[i]);
		if(t[i] == 1){
			scanf("%I64d%I64d",&a[i],&b[i]);
		}else{
			scanf("%I64d",&a[i]);
		}
		ans[i] = -INF;
		ans2[i] = -INF;
	}

	int LEN = sqrt(n);
	Point pt_in_block[555];
	pair<ll,int> query_in_block[555];
	int cntq = 0;
	int k = 0;
	for(int s=1;s<=n;s+=LEN){
		int e = min(n+1,s+LEN);
		cntq = 0;
		//cout<<"handle segment "<<s<<" "<<e<<endl;
		for(int i=s;i<e;i++){
			//cout<<"--calc "<<i<<endl;
			if(t[i] == 3){
				for(int j=s;j<e;j++){
					if(t[j] == 1 && j < i && !ban[j]){
						ans[i] = max(ans[i],b[j]+a[j]*a[i]);
					}else if(t[j] == 2 && j > i && a[j] < i){
						int aa = a[a[j]];
						int bb = b[a[j]];
						ans[i] = max(ans[i],bb+aa*a[i]);
					}
				}
				query_in_block[cntq++] = make_pair(a[i],i);
			}else if(t[i] == 2){
				ban[a[i]] = 1;
			}
		}

		sort(query_in_block,query_in_block+cntq);
		ConvexHull(s-1);
		if(sz == 0){	//empty set
			continue;
		}else{
			int pos = 0;
			for(int i=0;i<cntq;i++){
				while(pos<sz){
					ll val = ch[pos].y + query_in_block[i].first*ch[pos].x;
					if( val > ans2[query_in_block[i].second]){
						ans2[query_in_block[i].second] = val;
					//	cout<<"modify "<<query_in_block[i].second<<endl;
					}else{
						if(pos){
							pos--;
						}
						break;
					}

					pos++;
					if(pos==sz){
						if(pos)pos--;
						break;
					}
				}
			}
		}
	}

	for(int i=1;i<=n;i++){
		if(t[i] == 3){
			ll a = max(ans[i],ans2[i]);
			if(a == -INF){
				printf("EMPTY SET\n");
			}else{
				printf("%I64d\n",a);
			}
		}
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 300010;
const ll INF = 2e18;

int t[maxn];
ll a[maxn];
ll b[maxn];
ll ans[maxn];
int r[maxn];

inline int getID(int l,int r){
	return (l+r)|(l<r);
}

struct Point{
	ll x,y;
	Point(ll x,ll y):x(x),y(y){
	}
	Point(){
	}
	bool operator<(const Point &other)const{
		if(x!=other.x){
			return x<other.x;
		}
		return y>other.y;
	}
};

Point ch[maxn];
vector<Point> pts[maxn<<1];

void update(int tl,int tr,int l,int r,Point pt){
	if(l == tl && r == tr){
		//cout<<"update Point "<<pt.x<<","<<pt.y<<" to "<<l<<" "<<r<<endl;
		pts[getID(l,r)].push_back(pt);
		return;
	}
	int mid = (tl+tr)>>1;
	if(r <= mid){
		update(tl,mid,l,r,pt);
	}else{
		if(l > mid){
			update(mid+1,tr,l,r,pt);
		}else{
			update(tl,mid,l,mid,pt);
			update(mid+1,tr,mid+1,r,pt);
		}
	}
}

int sz;	//ConvexHull's size

int n;
int k;

void ConvexHull(int id){
	sz = 0;
	Point pre = Point(-INF,-INF);
	for(int i=0;i<pts[id].size();i++){
		Point pt = pts[id][i];
		if(pt.x == pre.x){
			continue;
		}
		pre = pt;
		if(sz<2){
			ch[sz++] = pt;
		}else{
			while(sz>=2 && (pt.y-ch[sz-1].y)*(ch[sz-1].x-ch[sz-2].x) >=
					(ch[sz-1].y-ch[sz-2].y)*(pt.x-ch[sz-1].x) ){
				sz--;
			}
			ch[sz++] = pt;
		}
	}
}

inline ll calc(int ptid,int qid){
	return ch[ptid].y+ch[ptid].x*a[qid];
}

ll bs(int l,int r,int qid){
	int L = l;
	int R = r;
	ll res = -INF;
	while(l<=r){
		int mid = (l+r)>>1;
		ll mval = calc(mid,qid);

		res = max(res,mval);

		if(mid > L && calc(mid-1,qid) > mval){
			r = mid-1;
		}else if(mid < R && calc(mid+1,qid) > mval){
			l = mid+1;
		}else{
			break;
		}
	}
	return res;
}

void cdq(int l,int r){
	int mid = (l+r)>>1;

	if(l<r)cdq(l,mid);
	if(l<r)cdq(mid+1,r);

	//
	sort(pts[getID(l,r)].begin(),pts[getID(l,r)].end());
	ConvexHull(getID(l,r));
	for(int i=l;i<=r;i++){
		if(t[i] == 3){
			ans[i] = max(ans[i],bs(0,sz-1,i));
		}
	}
}

int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&t[i]);
		if(t[i] == 1){
			scanf("%I64d%I64d",&a[i],&b[i]);
			r[i] = n;
		}else{
			scanf("%I64d",&a[i]);
			if(t[i] == 2){
				r[a[i]] = i-1;
			}
		}
		ans[i] = -INF;
	}

	for(int i=1;i<=n;i++){
		if(t[i] == 1){
			update(1,n,i,r[i],Point(a[i],b[i]));
		}
	}

	cdq(1,n);

	for(int i=1;i<=n;i++){
		if(t[i] == 3){
			if(ans[i] == -INF){
				printf("EMPTY SET\n");
			}else{
				printf("%I64d\n",ans[i]);
			}
		}
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 300010;
const ll INF = 2e18;

int t[maxn];
ll a[maxn];
ll b[maxn];
bool ban[maxn];
ll ans[maxn];
ll ans2[maxn];

struct Point{
	ll x,y;
	Point(ll x,ll y):x(x),y(y){
	}
	Point(){
	}

	bool operator<(const Point &other)const{
		if(x!=other.x){
			return x<other.x;
		}
		return y>other.y;
	}
};

//Point pts[maxn];
set<Point> pts;
Point ch[maxn];

int sz;

void ConvexHull(){
	int k = 0;
	/*
	for(int i=1;i<=n;i++){
		if(t[i]==1 && !ban[i]){
			pts[k++] = Point(a[i],b[i]);
		}
	}
	sort(pts,pts+k);
	*/
	sz = 0;
	for(auto pt:pts){
		if(sz<2){
			ch[sz++] = pt;
		}else{
			while(sz>=2 && (pt.y-ch[sz-1].y)*(ch[sz-1].x-ch[sz-2].x) >=
					(ch[sz-1].y-ch[sz-2].y)*(pt.x-ch[sz-1].x) ){
				sz--;
			}
			ch[sz++] = pt;
		}
	}
}

int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&t[i]);
		if(t[i] == 1){
			scanf("%I64d%I64d",&a[i],&b[i]);
		}else{
			scanf("%I64d",&a[i]);
		}
		ans[i] = -INF;
		ans2[i] = -INF;
	}

	int LEN = sqrt(n);
	Point pt_in_block[555];
	pair<ll,int> query_in_block[555];
	int cntq = 0;
	int k = 0;
	for(int s=1;s<=n;s+=LEN){
		int e = min(n+1,s+LEN);
		cntq = 0;
		//cout<<"handle segment "<<s<<" "<<e<<endl;
		for(int i=s;i<e;i++){
			//cout<<"--calc "<<i<<endl;
			if(t[i] == 3){
				for(int j=s;j<e;j++){
					if(t[j] == 1 && j < i && !ban[j]){
						ans[i] = max(ans[i],b[j]+a[j]*a[i]);
					}else if(t[j] == 2 && j > i && a[j] < i){
						int aa = a[a[j]];
						int bb = b[a[j]];
						ans[i] = max(ans[i],bb+aa*a[i]);
					}
				}
				query_in_block[cntq++] = make_pair(a[i],i);
			}else if(t[i] == 2){
				ban[a[i]] = 1;
				pts.erase(Point(a[a[i]],b[a[i]]));
			}
		}

		sort(query_in_block,query_in_block+cntq);
		ConvexHull();
		if(sz != 0){
			int pos = 0;
			for(int i=0;i<cntq;i++){
				while(pos<sz){
					ll val = ch[pos].y + query_in_block[i].first*ch[pos].x;
					if( val > ans2[query_in_block[i].second]){
						ans2[query_in_block[i].second] = val;
					//	cout<<"modify "<<query_in_block[i].second<<endl;
					}else{
						if(pos){
							pos--;
						}
						break;
					}

					pos++;
					if(pos==sz){
						if(pos)pos--;
						break;
					}
				}
			}
		}
		for(int i=s;i<e;i++){
			if(t[i] == 1 && !ban[i]){
				pts.insert(Point(a[i],b[i]));
			}
		}
	}

	for(int i=1;i<=n;i++){
		if(t[i] == 3){
			ll a = max(ans[i],ans2[i]);
			if(a == -INF){
				printf("EMPTY SET\n");
			}else{
				printf("%I64d\n",a);
			}
		}
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 300010;
const ll INF = 2e18;

int t[maxn];
ll a[maxn];
ll b[maxn];
bool ban[maxn];
ll ans[maxn];

struct Point{
	int x,y;
	Point(int x,int y):x(x),y(y){
	}
	Point(){
	}

	bool operator<(const Point &other)const{
		if(x!=other.x){
			return x<other.x;
		}
		return y>other.y;
	}
};

Point pts[maxn];
Point ch[maxn];

int sz;

void ConvexHull(int n){
	int k = 0;
	for(int i=1;i<=n;i++){
		if(t[i]==1 && !ban[i]){
			pts[k++] = Point(a[i],b[i]);
		}
	}
	sort(pts,pts+k);
	sz = 0;
	for(int i=0;i<k;i++){
		if(i && pts[i].x == pts[i-1].x){
			continue;
		}
		if(sz<2){
			ch[sz++] = pts[i];
		}else{
			while(sz>=2 && (pts[i].y-ch[sz-1].y)*(ch[sz-1].x-ch[sz-2].x) >
					(ch[sz-1].y-ch[sz-2].y)*(pts[i].x-ch[sz-1].x) ){
				sz--;
			}
			ch[sz++] = pts[i];
		}
	}
}

int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&t[i]);
		if(t[i] == 1){
			scanf("%I64d%I64d",&a[i],&b[i]);
		}else{
			scanf("%I64d",&a[i]);
		}
		ans[i] = -INF;
	}

	int LEN = sqrt(n);
	Point pt_in_block[555];
	pair<ll,int> query_in_block[555];
	int cntq = 0;
	int k = 0;
	for(int s=1;s<=n;s+=LEN){
		int e = min(n+1,s+LEN);
		cntq = 0;
		//cout<<"handle segment "<<s<<" "<<e<<endl;
		for(int i=s;i<e;i++){
			//cout<<"--calc "<<i<<endl;
			if(t[i] == 3){
				for(int j=s;j<e;j++){
					if(t[j] == 1 && j < i && !ban[j]){
						ans[i] = max(ans[i],b[j]+a[j]*a[i]);
					}else if(t[j] == 2 && j > i && a[j] < i){
						int aa = a[a[j]];
						int bb = b[a[j]];
						ans[i] = max(ans[i],bb+aa*a[i]);
					}
				}
				query_in_block[cntq++] = make_pair(a[i],i);
			}else if(t[i] == 2){
				ban[a[i]] = 1;
			}
		}

		sort(query_in_block,query_in_block+cntq);
		ConvexHull(s-1);
		if(sz == 0){	//empty set
			continue;
		}else{
			int pos = 0;
			for(int i=0;i<cntq;i++){
				while(pos<sz){
					ll val = ch[pos].y + query_in_block[i].first*ch[pos].x;
					if( val > ans[query_in_block[i].second]){
						ans[query_in_block[i].second] = val;
					//	cout<<"modify "<<query_in_block[i].second<<endl;
					}else{
						if(pos){
							pos--;
						}
						break;
					}

					pos++;
					if(pos==sz){
						if(pos)pos--;
						break;
					}
				}
			}
		}
	}

	for(int i=1;i<=n;i++){
		if(t[i] == 3){
			if(ans[i] == -INF){
				printf("EMPTY SET\n");
			}else{
				printf("%I64d\n",ans[i]);
			}
		}
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 300010;
const ll INF = 2e18;

int t[maxn];
ll a[maxn];
ll b[maxn];
bool ban[maxn];
ll ans[maxn];

struct Point{
	ll x,y;
	Point(ll x,ll y):x(x),y(y){
	}
	Point(){
	}

	bool operator<(const Point &other)const{
		if(x!=other.x){
			return x<other.x;
		}
		return y>other.y;
	}
};

Point pts[maxn];
Point ch[maxn];
Point p2[maxn];

int sz;	//ConvexHull's size

int n;
int k;

void ConvexHull(){
	sort(p2,p2+k);
	sz = 0;
	Point pre = Point(-INF,-INF);
	for(int i=0;i<k;i++){
		Point pt = p2[i];
		if(pt.x == pre.x){
			continue;
		}
		pre = pt;
		if(sz<2){
			ch[sz++] = pt;
		}else{
			while(sz>=2 && (pt.y-ch[sz-1].y)*(ch[sz-1].x-ch[sz-2].x) >=
					(ch[sz-1].y-ch[sz-2].y)*(pt.x-ch[sz-1].x) ){
				sz--;
			}
			ch[sz++] = pt;
		}
	}
}

inline ll calc(int ptid,int qid){
	return ch[ptid].y+ch[ptid].x*a[qid];
}

ll bs(int l,int r,int qid){
	int L = l;
	int R = r;
	ll res = -INF;
	while(l<=r){
		int mid = (l+r)>>1;
		ll mval = calc(mid,qid);

		res = max(res,mval);

		if(mid > L && calc(mid-1,qid) > mval){
			r = mid-1;
		}else if(mid < R && calc(mid+1,qid) > mval){
			l = mid+1;
		}else{
			break;
		}
	}
	return res;
}

void cdq(int l,int r){
	int mid = (l+r)>>1;

	if(l<r)cdq(mid+1,r);
	if(l<r)cdq(l,mid);

//	cout<<" cdqing "<<l<<" "<<r<<endl;
	//
	k=0;
	for(int i=l;i<=mid;i++){
		if(t[i]==1 && !ban[i]){
			p2[k++] = pts[i];
		}
	}
	ConvexHull();
	//cout<<"sz = "<<sz<<endl;
	for(int i=mid+1;i<=r;i++){
		if(t[i] == 3){
			// find best
			ans[i] = max(ans[i],bs(0,sz-1,i));
	//		cout<<"get "<<ans[i]<<endl;
		}
	}

	//
	k=0;
	for(int i=mid+1;i<=r;i++){
		if(t[i]==2 && a[i]<l){
			p2[k++] = pts[a[i]];
		}
	}
	ConvexHull();
	//cout<<"sz = "<<sz<<endl;
	for(int i=l;i<=mid;i++){
		if(t[i] == 3){
			ans[i] = max(ans[i],bs(0,sz-1,i));
		//	cout<<"get "<<ans[i]<<endl;
		}
	}

}

int main(){
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&t[i]);
		if(t[i] == 1){
			scanf("%I64d%I64d",&a[i],&b[i]);
			pts[i] = Point(a[i],b[i]);
			//ppi[k++] = make_pair(Point(a[i],b[i]),i);
		}else{
			scanf("%I64d",&a[i]);
			if(t[i] == 2){
				ban[a[i]] = 1;
			}
		}
		ans[i] = -INF;
	}

	cdq(1,n);

	for(int i=1;i<=n;i++){
		if(t[i] == 3){
			if(ans[i] == -INF){
				printf("EMPTY SET\n");
			}else{
				printf("%I64d\n",ans[i]);
			}
		}
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 300010;
const ll INF = 2e18;

int t[maxn];
ll a[maxn];
ll b[maxn];
bool ban[maxn];
ll ans[maxn];
ll ans2[maxn];

struct Point{
	ll x,y;
	Point(ll x,ll y):x(x),y(y){
	}
	Point(){
	}

	bool operator<(const Point &other)const{
		if(x!=other.x){
			return x<other.x;
		}
		return y>other.y;
	}
};

//Point pts[maxn];
multiset<Point> pts;
Point ch[maxn];

int sz;

void ConvexHull(){
	int k = 0;
	/*
	for(int i=1;i<=n;i++){
		if(t[i]==1 && !ban[i]){
			pts[k++] = Point(a[i],b[i]);
		}
	}
	sort(pts,pts+k);
	*/
	sz = 0;
	for(auto pt:pts){
		if(sz<2){
			ch[sz++] = pt;
		}else{
			while(sz>=2 && (pt.y-ch[sz-1].y)*(ch[sz-1].x-ch[sz-2].x) >=
					(ch[sz-1].y-ch[sz-2].y)*(pt.x-ch[sz-1].x) ){
				sz--;
			}
			ch[sz++] = pt;
		}
	}
}

int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&t[i]);
		if(t[i] == 1){
			scanf("%I64d%I64d",&a[i],&b[i]);
		}else{
			scanf("%I64d",&a[i]);
		}
		ans[i] = -INF;
		ans2[i] = -INF;
	}

	int LEN = sqrt(n);
	Point pt_in_block[555];
	pair<ll,int> query_in_block[555];
	int cntq = 0;
	int k = 0;
	for(int s=1;s<=n;s+=LEN){
		int e = min(n+1,s+LEN);
		cntq = 0;
		//cout<<"handle segment "<<s<<" "<<e<<endl;
		for(int i=s;i<e;i++){
			//cout<<"--calc "<<i<<endl;
			if(t[i] == 3){
				for(int j=s;j<e;j++){
					if(t[j] == 1 && j < i && !ban[j]){
						ans[i] = max(ans[i],b[j]+a[j]*a[i]);
					}else if(t[j] == 2 && j > i && a[j] < i){
						int aa = a[a[j]];
						int bb = b[a[j]];
						ans[i] = max(ans[i],bb+aa*a[i]);
					}
				}
				query_in_block[cntq++] = make_pair(a[i],i);
			}else if(t[i] == 2){
				ban[a[i]] = 1;
				pts.erase(Point(a[a[i]],b[a[i]]));
			}
		}

		sort(query_in_block,query_in_block+cntq);
		ConvexHull();
		if(sz != 0){
			int pos = 0;
			for(int i=0;i<cntq;i++){
				while(pos<sz){
					ll val = ch[pos].y + query_in_block[i].first*ch[pos].x;
					if( val > ans2[query_in_block[i].second]){
						ans2[query_in_block[i].second] = val;
					//	cout<<"modify "<<query_in_block[i].second<<endl;
					}else{
						if(pos){
							pos--;
						}
						break;
					}

					pos++;
					if(pos==sz){
						if(pos)pos--;
						break;
					}
				}
			}
		}
		for(int i=s;i<e;i++){
			if(t[i] == 1 && !ban[i]){
				pts.insert(Point(a[i],b[i]));
			}
		}
	}

	for(int i=1;i<=n;i++){
		if(t[i] == 3){
			ll a = max(ans[i],ans2[i]);
			if(a == -INF){
				printf("EMPTY SET\n");
			}else{
				printf("%I64d\n",a);
			}
		}
	}
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define ll long long

const int maxn = 300010;
const ll INF = 2e18;

int t[maxn];
ll a[maxn];
ll b[maxn];
bool ban[maxn];
ll ans[maxn];

struct Point{
	int x,y;
	Point(int x,int y):x(x),y(y){
	}
	Point(){
	}

	bool operator<(const Point &other)const{
		if(x!=other.x){
			return x<other.x;
		}
		return y>other.y;
	}
};

Point pts[maxn];
Point ch[maxn];

int sz;

void ConvexHull(int n){
	int k = 0;
	for(int i=1;i<=n;i++){
		if(t[i]==1 && !ban[i]){
			pts[k++] = Point(a[i],b[i]);
		}
	}
	sort(pts,pts+k);
	sz = 0;
	for(int i=0;i<k;i++){
		if(i && pts[i].x == pts[i-1].x){
			continue;
		}
		if(sz<2){
			ch[sz++] = pts[i];
		}else{
			while(sz>=2 && (pts[i].y-ch[sz-1].y)*(ch[sz-1].x-ch[sz-2].x) >
					(ch[sz-1].y-ch[sz-2].y)*(pts[i].x-ch[sz-1].x) ){
				sz--;
			}
			ch[sz++] = pts[i];
		}
	}
}

int main(){
	int n;
	cin>>n;
	for(int i=1;i<=n;i++){
		scanf("%d",&t[i]);
		if(t[i] == 1){
			scanf("%I64d%I64d",&a[i],&b[i]);
		}else{
			scanf("%I64d",&a[i]);
		}
		ans[i] = -INF;
	}

	int LEN = sqrt(n);
	Point pt_in_block[555];
	pair<ll,int> query_in_block[555];
	int cntq = 0;
	int k = 0;
	for(int s=1;s<=n;s+=LEN){
		int e = min(n+1,s+LEN);
		cntq = 0;
	//	cout<<"handle segment "<<s<<" "<<e<<endl;
		for(int i=s;i<e;i++){
		//	cout<<"--calc "<<i<<endl;
			if(t[i] == 3){
				for(int j=s;j<e;j++){
					if(t[j] == 1 && j < i){
						ans[i] = max(ans[i],b[i]+a[i]*a[j]);
					//	cout<<"?";
					}else if(t[j] == 2 && j > i && a[j]<i){
						int aa = a[a[j]];
						int bb = b[a[j]];
						ans[i] = max(ans[i],bb+aa*a[i]);
					//	cout<<"?";
					}
				}
				query_in_block[cntq++] = make_pair(a[i],i);
			}else if(t[i] == 2){
				ban[a[i]] = 1;
			}
		}

		sort(query_in_block,query_in_block+cntq);
		ConvexHull(s-1);
		if(sz == 0){	//empty set
			continue;
		}else{
			int pos = 0;
			for(int i=0;i<cntq;i++){
				while(pos<sz){
					ll val = ch[pos].y + query_in_block[i].first*ch[pos].x;
					if( val > ans[query_in_block[i].second]){
						ans[query_in_block[i].second] = val;
					//	cout<<"modify "<<query_in_block[i].second<<endl;
					}else{
						if(pos){
							pos--;
						}
						break;
					}

					pos++;
					if(pos==sz){
						if(pos)pos--;
						break;
					}
				}
			}
		}
	}

	for(int i=1;i<=n;i++){
		if(t[i] == 3){
			if(ans[i] == -INF){
				printf("EMPTY SET\n");
			}else{
				printf("%I64d\n",ans[i]);
			}
		}
	}
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define FOR(i, j, k) for(int i=(j); i<=(k); i++)
#define FFOR(i, j, k) for(int i=(j); i<(k); i++)
#define DFOR(i, j, k) for(int i=(j); i>=(k); i--)
#define bug(x) cerr<<#x<<" = "<<(x)<<'\n'
#define pb push_back
#define mp make_pair
#define setbit(s, i) (s|=(1LL<<(i)))
#define bit(s, i) (((s)>>(i))&1LL)
#define mask(i) ((1LL<<(i)))
#define builtin_popcount __builtin_popcountll
using ll=long long;
using ld=long double;
template <typename T> inline void read(T &x){
    char c;
    bool nega=0;
    while((!isdigit(c=getchar()))&&(c!='-'));
    if(c=='-'){
        nega=1;
        c=getchar();
    }
    x=c-48;
    while(isdigit(c=getchar())) x=x*10+c-48;
    if(nega) x=-x;
}
template <typename T> inline void writep(T x){
    if(x>9) writep(x/10);
    putchar(x%10+48);
}
template <typename T> inline void write(T x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    writep(x);
}
template <typename T> inline void writeln(T x){
    write(x);
    putchar('\n');
}
#define taskname "F"
int n;
ll ans[300001];
const ll inf=mask(62);
int deleted_at[300001];
ll a[300001];
map <ll, int> M;
class query{
public:
    int t, id;
    vector <ll> data;
    void input(int id){
        this->id=id;
        read(t);
        data.resize(1+(t==1));
        for(ll &x: data) read(x);
        if(t==1) deleted_at[id]=n+1;
        else if(t==2) deleted_at[data[0]]=id;
        else if(t==3){
            ans[id]=-inf;
            M[data[0]]=0;
        }
    }
} q[300001];
class line{
public:
    int a, b;
    line(int a, int b){
        this->a=a;
        this->b=b;
    }
    line(){
        a=-2e9;
        b=0;
    }
    ll at(ll x){
        if(a==-2e9) return -inf;
        return x*a+b;
    }
};
class linear_segment_tree{
public:
    using pointer=linear_segment_tree*;
    line L;
    pointer left, right;
    linear_segment_tree(){
        L=line();
        left=right=nullptr;
    }
    void update(line A, int l, int r){
        int m=(l+r)/2;
        bool gl=A.at(a[l])>=L.at(a[l]);
        bool gr=A.at(a[r])>=L.at(a[r]);
        if(gl&&gr){
            L=A;
            return;
        }
        else if(l!=r){
            if(left==nullptr){
                left=new linear_segment_tree();
                right=new linear_segment_tree();
            }
            left->update(A, l, m);
            right->update(A, m+1, r);
        }
    }
    ll get(int u, int l, int r){
        int m=(l+r)/2;
        ll res=L.at(a[u]);
        if(l!=r){
            if(left!=nullptr){
                if(m>=u) res=max(res, left->get(u, l, m));
                else res=max(res, right->get(u, m+1, r));
            }
        }
        return res;
    }
};
class segment_tree{
public:
    using pointer=segment_tree*;
    linear_segment_tree::pointer tree;
    int l, r, m;
    pointer left, right;
    segment_tree(int l, int r){
        tree=new linear_segment_tree();
        this->l=l;
        this->r=r;
        m=(l+r)/2;
        if(l!=r){
            left=new segment_tree(l, m);
            right=new segment_tree(m+1, r);
        }
        else left=right=nullptr;
    }
    void update(line L, int u, int v){
        if(l>v||r<u) return;
        if(u<=l&&v>=r) tree->update(L, 1, M.size());
        else{
            left->update(L, u, v);
            right->update(L, u, v);
        }
    }
    ll get(int u, int i){
        if(l==r) return tree->get(i, 1, M.size());
        else if(m>=u) return max(tree->get(i, 1, M.size()), left->get(u, i));
        else return max(tree->get(i, 1, M.size()), right->get(u, i));
    }
};
segment_tree::pointer tree;
int main(){
    #ifdef Uiharu
        if(fopen(taskname".in", "r"))
            freopen(taskname".in", "r", stdin);
    #endif // Uiharu
    read(n);
    FOR(i, 1, n) q[i].input(i);
    {
        int cnt=0;
        for(auto &t: M){
            cnt++;
            t.second=cnt;
            a[cnt]=t.first;
        }
    }
    tree=new segment_tree(1, n);
    FOR(i, 1, n){
        if(q[i].t==1){
            tree->update(line(q[i].data[0], q[i].data[1]), i, deleted_at[i]-1);
        }
    }
    FOR(i, 1, n) if(q[i].t==3){
        ll res=tree->get(i, M[q[i].data[0]]);
        if(res==-inf) puts("EMPTY SET");
        else writeln(res);
    }
}


#include <bits/stdc++.h>
using namespace std;
#define FOR(i, j, k) for(int i=(j); i<=(k); i++)
#define FFOR(i, j, k) for(int i=(j); i<(k); i++)
#define DFOR(i, j, k) for(int i=(j); i>=(k); i--)
#define bug(x) cerr<<#x<<" = "<<(x)<<'\n'
#define pb push_back
#define mp make_pair
#define setbit(s, i) (s|=(1LL<<(i)))
#define bit(s, i) (((s)>>(i))&1LL)
#define mask(i) ((1LL<<(i)))
#define builtin_popcount __builtin_popcountll
using ll=long long;
using ld=long double;
template <typename T> inline void read(T &x){
    char c;
    bool nega=0;
    while((!isdigit(c=getchar()))&&(c!='-'));
    if(c=='-'){
        nega=1;
        c=getchar();
    }
    x=c-48;
    while(isdigit(c=getchar())) x=x*10+c-48;
    if(nega) x=-x;
}
template <typename T> inline void writep(T x){
    if(x>9) writep(x/10);
    putchar(x%10+48);
}
template <typename T> inline void write(T x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    writep(x);
}
template <typename T> inline void writeln(T x){
    write(x);
    putchar('\n');
}
#define taskname "F"
int n;
ll ans[300001];
const ll inf=mask(62);
int deleted_at[300001];
ll a[300001];
map <ll, int> M;
class query{
public:
    int t, id;
    vector <ll> data;
    void input(int id){
        this->id=id;
        read(t);
        data.resize(1+(t==1));
        for(ll &x: data) read(x);
        if(t==1) deleted_at[id]=n+1;
        else if(t==2) deleted_at[data[0]]=id;
        else if(t==3){
            ans[id]=-inf;
            M[data[0]]=0;
        }
    }
} q[300001];
class line{
public:
    ll a, b;
    line(ll a, ll b){
        this->a=a;
        this->b=b;
    }
    line(){
        a=0;
        b=-inf;
    }
    ll at(ll x){
        return a*x+b;
    }
};
class linear_segment_tree{
public:
    using pointer=linear_segment_tree*;
    line L;
    int l, r, m;
    pointer left, right;
    linear_segment_tree(int l, int r){
        this->l=l;
        this->r=r;
        m=(l+r)/2;
        L=line();
        left=right=nullptr;
    }
    ~linear_segment_tree(){
        if(left!=nullptr){
            delete left;
            delete right;
        }
    }
    void update(line A){
        bool gl=A.at(a[l])>=L.at(a[l]);
        bool gr=A.at(a[r])>=L.at(a[r]);
        if(gl&&gr){
            L=A;
            return;
        }
        else if(l!=r){
            if(left==nullptr){
                left=new linear_segment_tree(l, m);
                right=new linear_segment_tree(m+1, r);
            }
            left->update(A);
            right->update(A);
        }
    }
    ll get(int u){
        ll res=L.at(a[u]);
        if(l!=r){
            if(left!=nullptr){
                if(m>=u) res=max(res, left->get(u));
                else res=max(res, right->get(u));
            }
        }
        return res;
    }
};
vector <pair <int, int> > Q[600001];
vector <line> A[600001];
int sz=0;
class segment_tree{
public:
    using pointer=segment_tree*;
    int l, r, m;
    int id;
    pointer left, right;
    segment_tree(int l, int r){
        this->l=l;
        this->r=r;
        m=(l+r)/2;
        sz++;
        id=sz;
        if(l!=r){
            left=new segment_tree(l, m);
            right=new segment_tree(m+1, r);
        }
        else left=right=nullptr;
    }
    void update(line L, int u, int v){
        if(l>v||r<u) return;
        if(u<=l&&v>=r) A[id].pb(L);
        else{
            left->update(L, u, v);
            right->update(L, u, v);
        }
    }
    void mark(int u, int i){
        Q[id].pb(mp(u, i));
        if(l!=r){
            if(m>=u) left->mark(u, i);
            else right->mark(u, i);
        }
    }
    void solve(){
        linear_segment_tree::pointer tree=new linear_segment_tree(1, M.size());
        for(line L: A[id]) tree->update(L);
        for(pair <int, int> p: Q[id]) ans[p.first]=max(ans[p.first], tree->get(p.second));
        delete tree;
        if(left!=nullptr){
            left->solve();
            right->solve();
        }
    }
};
segment_tree::pointer tree;
int main(){
    #ifdef Uiharu
        if(fopen(taskname".in", "r"))
            freopen(taskname".in", "r", stdin);
    #endif // Uiharu
    read(n);
    FOR(i, 1, n) q[i].input(i);
    {
        int cnt=0;
        for(auto &t: M){
            cnt++;
            t.second=cnt;
            a[cnt]=t.first;
        }
    }
    tree=new segment_tree(1, n);
    FOR(i, 1, n){
        if(q[i].t==1) tree->update(line(q[i].data[0], q[i].data[1]), i, deleted_at[i]-1);
        else if(q[i].t==3) tree->mark(i, M[q[i].data[0]]);
    }
    tree->solve();
    FOR(i, 1, n) if(q[i].t==3){
        if(ans[i]==-inf) puts("EMPTY SET");
        else writeln(ans[i]);
    }
}


#include <bits/stdc++.h>
using namespace std;
#define FOR(i, j, k) for(int i=(j); i<=(k); i++)
#define FFOR(i, j, k) for(int i=(j); i<(k); i++)
#define DFOR(i, j, k) for(int i=(j); i>=(k); i--)
#define bug(x) cerr<<#x<<" = "<<(x)<<'\n'
#define pb push_back
#define mp make_pair
#define setbit(s, i) (s|=(1LL<<(i)))
#define bit(s, i) (((s)>>(i))&1LL)
#define mask(i) ((1LL<<(i)))
#define builtin_popcount __builtin_popcountll
using ll=long long;
using ld=long double;
template <typename T> inline void read(T &x){
    char c;
    bool nega=0;
    while((!isdigit(c=getchar()))&&(c!='-'));
    if(c=='-'){
        nega=1;
        c=getchar();
    }
    x=c-48;
    while(isdigit(c=getchar())) x=x*10+c-48;
    if(nega) x=-x;
}
template <typename T> inline void writep(T x){
    if(x>9) writep(x/10);
    putchar(x%10+48);
}
template <typename T> inline void write(T x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    writep(x);
}
template <typename T> inline void writeln(T x){
    write(x);
    putchar('\n');
}
#define taskname "F"
int n;
ll ans[300001];
const ll inf=mask(62);
int deleted_at[300001];
ll a[300001];
map <ll, int> M;
class query{
public:
    int t, id;
    vector <ll> data;
    void input(int id){
        this->id=id;
        read(t);
        data.resize(1+(t==1));
        for(ll &x: data) read(x);
        if(t==1) deleted_at[id]=n+1;
        if(t==2) deleted_at[data[0]]=id;
        else if(t==3){
            ans[id]=-inf;
            M[data[0]]=0;
        }
    }
} q[300001];
class line{
public:
    ll a, b;
    line(ll a, ll b){
        this->a=a;
        this->b=b;
    }
    line(){
        a=0;
        b=-inf;
    }
    ll at(ll x){
        return a*x+b;
    }
};
class linear_segment_tree{
public:
    using pointer=linear_segment_tree*;
    line L;
    int l, r, m;
    pointer left, right;
    linear_segment_tree(int l, int r){
        this->l=l;
        this->r=r;
        m=(l+r)/2;
        L=line();
        left=right=nullptr;
    }
    void update(line A){
        bool gl=A.at(a[l])>=L.at(a[l]);
        bool gr=A.at(a[r])>=L.at(a[r]);
        if(gl&&gr){
            L=A;
            return;
        }
        else if(l!=r){
            if(left==nullptr){
                left=new linear_segment_tree(l, m);
                right=new linear_segment_tree(m+1, r);
            }
            left->update(A);
            right->update(A);
        }
    }
    ll get(int u){
        ll res=L.at(a[u]);
        if(l!=r){
            if(left!=nullptr){
                if(m>=u) res=max(res, left->get(u));
                else res=max(res, right->get(u));
            }
        }
        return res;
    }
};
class segment_tree{
public:
    using pointer=segment_tree*;
    linear_segment_tree::pointer tree;
    int l, r, m;
    pointer left, right;
    segment_tree(int l, int r){
        tree=new linear_segment_tree(1, M.size());
        this->l=l;
        this->r=r;
        m=(l+r)/2;
        if(l!=r){
            left=new segment_tree(l, m);
            right=new segment_tree(m+1, r);
        }
        else left=right=nullptr;
    }
    void update(line L, int u, int v){
        if(l>v||r<u) return;
        if(u<=l&&v>=r) tree->update(L);
        else{
            left->update(L, u, v);
            right->update(L, u, v);
        }
    }
    ll get(int u, int i){
        if(l==r) return tree->get(i);
        else if(m>=u) return max(tree->get(i), left->get(u, i));
        else return max(tree->get(i), right->get(u, i));
    }
};
segment_tree::pointer tree;
int main(){
    #ifdef Uiharu
        if(fopen(taskname".in", "r"))
            freopen(taskname".in", "r", stdin);
    #endif // Uiharu
    read(n);
    FOR(i, 1, n) q[i].input(i);
    {
        int cnt=0;
        for(auto t: M){
            cnt++;
            t.second=cnt;
            a[cnt]=t.first;
        }
    }
    tree=new segment_tree(1, n);
    FOR(i, 1, n){
        if(q[i].t==1){
            tree->update(line(q[i].data[0], q[i].data[1]), i, deleted_at[i]-1);
        }
    }
    FOR(i, 1, n) if(q[i].t==3){
        ll res=tree->get(i, q[i].data[0]);
        if(res==-inf) puts("EMPTY SET");
        else writeln(res);
    }
}


#include <bits/stdc++.h>
using namespace std;
#define FOR(i, j, k) for(int i=(j); i<=(k); i++)
#define FFOR(i, j, k) for(int i=(j); i<(k); i++)
#define DFOR(i, j, k) for(int i=(j); i>=(k); i--)
#define bug(x) cerr<<#x<<" = "<<(x)<<'\n'
#define pb push_back
#define mp make_pair
#define setbit(s, i) (s|=(1LL<<(i)))
#define bit(s, i) (((s)>>(i))&1LL)
#define mask(i) ((1LL<<(i)))
#define builtin_popcount __builtin_popcountll
using ll=long long;
using ld=long double;
template <typename T> inline void read(T &x){
    char c;
    bool nega=0;
    while((!isdigit(c=getchar()))&&(c!='-'));
    if(c=='-'){
        nega=1;
        c=getchar();
    }
    x=c-48;
    while(isdigit(c=getchar())) x=x*10+c-48;
    if(nega) x=-x;
}
template <typename T> inline void writep(T x){
    if(x>9) writep(x/10);
    putchar(x%10+48);
}
template <typename T> inline void write(T x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    writep(x);
}
template <typename T> inline void writeln(T x){
    write(x);
    putchar('\n');
}
#define taskname "F"
int n;
ll ans[300001];
const ll inf=mask(62);
int deleted_at[300001];
ll a[300001];
map <ll, int> M;
class query{
public:
    int t, id;
    vector <ll> data;
    void input(int id){
        this->id=id;
        read(t);
        data.resize(1+(t==1));
        for(ll &x: data) read(x);
        if(t==1) deleted_at[id]=n+1;
        else if(t==2) deleted_at[data[0]]=id;
        else if(t==3){
            ans[id]=-inf;
            M[data[0]]=0;
        }
    }
} q[300001];
class line{
public:
    ll a, b;
    line(ll a, ll b){
        this->a=a;
        this->b=b;
    }
    line(){
        a=0;
        b=-inf;
    }
    ll at(ll x){
        return a*x+b;
    }
};
class linear_segment_tree{
public:
    using pointer=linear_segment_tree*;
    line L;
    int l, r, m;
    pointer left, right;
    linear_segment_tree(int l, int r){
        this->l=l;
        this->r=r;
        m=(l+r)/2;
        L=line();
        left=right=nullptr;
    }
    ~linear_segment_tree(){
        if(left!=nullptr){
            delete left;
            delete right;
        }
    }
    void update(line A){
        bool gl=A.at(a[l])>=L.at(a[l]);
        bool gr=A.at(a[r])>=L.at(a[r]);
        if(gl&&gr){
            L=A;
            return;
        }
        else if(l!=r){
            if(left==nullptr){
                left=new linear_segment_tree(l, m);
                right=new linear_segment_tree(m+1, r);
            }
            left->update(A);
            right->update(A);
        }
    }
    ll get(int u){
        ll res=L.at(a[u]);
        if(l!=r){
            if(left!=nullptr){
                if(m>=u) res=max(res, left->get(u));
                else res=max(res, right->get(u));
            }
        }
        return res;
    }
};
class segment_tree{
public:
    using pointer=segment_tree*;
    list <pair <int, int> > q;
    list <line> A;
    int l, r, m;
    pointer left, right;
    segment_tree(int l, int r){
        this->l=l;
        this->r=r;
        m=(l+r)/2;
        if(l!=r){
            left=new segment_tree(l, m);
            right=new segment_tree(m+1, r);
        }
        else left=right=nullptr;
    }
    void update(line L, int u, int v){
        if(l>v||r<u) return;
        if(u<=l&&v>=r) A.pb(L);
        else{
            left->update(L, u, v);
            right->update(L, u, v);
        }
    }
    void mark(int u, int i){
        q.pb(mp(u, i));
        if(l!=r){
            if(m>=u) left->mark(u, i);
            else right->mark(u, i);
        }
    }
    void solve(){
        linear_segment_tree::pointer tree=new linear_segment_tree(1, M.size());
        for(line L: A) tree->update(L);
        for(pair <int, int> p: q) ans[p.first]=max(ans[p.first], tree->get(p.second));
        delete tree;
        if(left!=nullptr){
            left->solve();
            right->solve();
        }
    }
};
segment_tree::pointer tree;
int main(){
    #ifdef Uiharu
        if(fopen(taskname".in", "r"))
            freopen(taskname".in", "r", stdin);
    #endif // Uiharu
    read(n);
    FOR(i, 1, n) q[i].input(i);
    {
        int cnt=0;
        for(auto &t: M){
            cnt++;
            t.second=cnt;
            a[cnt]=t.first;
        }
    }
    tree=new segment_tree(1, n);
    FOR(i, 1, n){
        if(q[i].t==1) tree->update(line(q[i].data[0], q[i].data[1]), i, deleted_at[i]-1);
        else if(q[i].t==3) tree->mark(i, M[q[i].data[0]]);
    }
    tree->solve();
    FOR(i, 1, n) if(q[i].t==3){
        if(ans[i]==-inf) puts("EMPTY SET");
        else writeln(ans[i]);
    }
}


 #include <bits/stdc++.h>
using namespace std;
#define FOR(i, j, k) for(int i=(j); i<=(k); i++)
#define FFOR(i, j, k) for(int i=(j); i<(k); i++)
#define DFOR(i, j, k) for(int i=(j); i>=(k); i--)
#define bug(x) cerr<<#x<<" = "<<(x)<<'\n'
#define pb push_back
#define mp make_pair
#define setbit(s, i) (s|=(1LL<<(i)))
#define bit(s, i) (((s)>>(i))&1LL)
#define mask(i) ((1LL<<(i)))
#define builtin_popcount __builtin_popcountll
using ll=long long;
using ld=long double;
template <typename T> inline void read(T &x){
    char c;
    bool nega=0;
    while((!isdigit(c=getchar()))&&(c!='-'));
    if(c=='-'){
        nega=1;
        c=getchar();
    }
    x=c-48;
    while(isdigit(c=getchar())) x=x*10+c-48;
    if(nega) x=-x;
}
template <typename T> inline void writep(T x){
    if(x>9) writep(x/10);
    putchar(x%10+48);
}
template <typename T> inline void write(T x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    writep(x);
}
template <typename T> inline void writeln(T x){
    write(x);
    putchar('\n');
}
#define taskname "F"
int n;
ll ans[300001];
const ll inf=mask(62);
int deleted_at[300001];
ll a[300001];
map <ll, int> M;
class query{
public:
    int t, id;
    vector <ll> data;
    void input(int id){
        this->id=id;
        read(t);
        data.resize(1+(t==1));
        for(ll &x: data) read(x);
        if(t==1) deleted_at[id]=n+1;
        else if(t==2) deleted_at[data[0]]=id;
        else if(t==3) ans[id]=-inf;
    }
} q[300001];
class line{
public:
    ll a, b;
    line(ll a, ll b){
        this->a=a;
        this->b=b;
    }
    line(){
        a=0;
        b=-inf;
    }
    ll at(ll x){
        return a*x+b;
    }
};
const ll left_bound=-1000000000;
const ll right_bound=1000000000;
class convex_hull_trick{
public:
    vector <line> L;
    vector <pair <line, ll> > c;
    vector <pair <ll, int> > q;
    convex_hull_trick(){
        L.clear();
        c.clear();
        q.clear();
    }
    void insert(line A){
        L.pb(A);
    }
    void add_query(ll x, int u){
        q.pb(mp(x, u));
    }
    void construct(){
        sort(L.begin(), L.end(), [](line A, line B){
            return (A.a<B.a)||((A.a==B.a)&&(A.b<B.b));
        });
        for(line A: L){
            while(!c.empty()){
                if((c.size()==1)){
                    if(c[0].first.at(left_bound)<=A.at(left_bound)) c.pop_back();
                    else break;
                }
                else{
                    if(c.back().first.at(c[c.size()-2].second)<=A.at(c[c.size()-2].second)) c.pop_back();
                    else break;
                }
            }
            if(c.empty()) c.pb(mp(A, right_bound+1));
            else{
                ll x=(c.back().first.b-A.b)/(A.a-c.back().first.a);
                while(A.at(x)<c.back().first.at(x)) x++;
                c.back().second=x;
                c.pb(mp(A, right_bound+1));
            }
        }
    }
    void process_queries(){
        sort(q.begin(), q.end());
        if(c.empty()) return;
        int i=0;
        for(pair <ll, int> p: q){
            while(c[i].second<=p.first) i++;
            ans[p.second]=max(ans[p.second], c[i].first.at(p.first));
        }
    }
};
class segment_tree{
public:
    using pointer=segment_tree*;
    convex_hull_trick cht;
    int l, r, m;
    pointer left, right;
    segment_tree(int l, int r){
        this->l=l;
        this->r=r;
        m=(l+r)/2;
        if(l!=r){
            left=new segment_tree(l, m);
            right=new segment_tree(m+1, r);
        }
        else left=right=nullptr;
    }
    void update(line L, int u, int v){
        if(l>v||r<u) return;
        if(u<=l&&v>=r) cht.insert(L);
        else{
            left->update(L, u, v);
            right->update(L, u, v);
        }
    }
    void mark(int u, ll i){
        cht.add_query(i, u);
        if(l!=r){
            if(m>=u) return left->mark(u, i);
            else right->mark(u, i);
        }
    }
    void solve(){
        cht.construct();
        cht.process_queries();
        if(left!=nullptr){
            left->solve();
            right->solve();
        }
    }
};
segment_tree::pointer tree;
int main(){
    #ifdef Uiharu
        if(fopen(taskname".in", "r"))
            freopen(taskname".in", "r", stdin);
    #endif // Uiharu
    read(n);
    FOR(i, 1, n) q[i].input(i);
    tree=new segment_tree(1, n);
    FOR(i, 1, n){
        if(q[i].t==1) tree->update(line(q[i].data[0], q[i].data[1]), i, deleted_at[i]-1);
        else if(q[i].t==3) tree->mark(i, q[i].data[0]);
    }
    tree->solve();
    FOR(i, 1, n) if(q[i].t==3){
        if(ans[i]==-inf) puts("EMPTY SET");
        else writeln(ans[i]);
    }
}


#include <bits/stdc++.h>
using namespace std;
#define FOR(i, j, k) for(int i=(j); i<=(k); i++)
#define FFOR(i, j, k) for(int i=(j); i<(k); i++)
#define DFOR(i, j, k) for(int i=(j); i>=(k); i--)
#define bug(x) cerr<<#x<<" = "<<(x)<<'\n'
#define pb push_back
#define mp make_pair
#define setbit(s, i) (s|=(1LL<<(i)))
#define bit(s, i) (((s)>>(i))&1LL)
#define mask(i) ((1LL<<(i)))
#define builtin_popcount __builtin_popcountll
using ll=long long;
using ld=long double;
template <typename T> inline void read(T &x){
    char c;
    bool nega=0;
    while((!isdigit(c=getchar()))&&(c!='-'));
    if(c=='-'){
        nega=1;
        c=getchar();
    }
    x=c-48;
    while(isdigit(c=getchar())) x=x*10+c-48;
    if(nega) x=-x;
}
template <typename T> inline void writep(T x){
    if(x>9) writep(x/10);
    putchar(x%10+48);
}
template <typename T> inline void write(T x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    writep(x);
}
template <typename T> inline void writeln(T x){
    write(x);
    putchar('\n');
}
#define taskname "F"
int n;
ll ans[300001];
const ll inf=mask(62);
int deleted_at[300001];
ll a[300001];
map <ll, int> M;
class query{
public:
    int t, id;
    vector <ll> data;
    void input(int id){
        this->id=id;
        read(t);
        data.resize(1+(t==1));
        for(ll &x: data) read(x);
        if(t==1) deleted_at[id]=n+1;
        else if(t==2) deleted_at[data[0]]=id;
        else if(t==3){
            ans[id]=-inf;
            M[data[0]]=0;
        }
    }
} q[300001];
class line{
public:
    ll a, b;
    line(ll a, ll b){
        this->a=a;
        this->b=b;
    }
    line(){
        a=0;
        b=-inf;
    }
    ll at(ll x){
        return a*x+b;
    }
};
class linear_segment_tree{
public:
    using pointer=linear_segment_tree*;
    line L;
    int l, r, m;
    pointer left, right;
    linear_segment_tree(int l, int r){
        this->l=l;
        this->r=r;
        m=(l+r)/2;
        L=line();
        left=right=nullptr;
    }
    void update(line A){
        bool gl=A.at(a[l])>=L.at(a[l]);
        bool gr=A.at(a[r])>=L.at(a[r]);
        if(gl&&gr){
            L=A;
            return;
        }
        else if(l!=r){
            if(left==nullptr){
                left=new linear_segment_tree(l, m);
                right=new linear_segment_tree(m+1, r);
            }
            left->update(A);
            right->update(A);
        }
    }
    ll get(int u){
        ll res=L.at(a[u]);
        if(l!=r){
            if(left!=nullptr){
                if(m>=u) res=max(res, left->get(u));
                else res=max(res, right->get(u));
            }
        }
        return res;
    }
};
class segment_tree{
public:
    using pointer=segment_tree*;
    linear_segment_tree::pointer tree;
    int l, r, m;
    pointer left, right;
    segment_tree(int l, int r){
        tree=new linear_segment_tree(1, M.size());
        this->l=l;
        this->r=r;
        m=(l+r)/2;
        if(l!=r){
            left=new segment_tree(l, m);
            right=new segment_tree(m+1, r);
        }
        else left=right=nullptr;
    }
    void update(line L, int u, int v){
        if(l>v||r<u) return;
        if(u<=l&&v>=r) tree->update(L);
        else{
            left->update(L, u, v);
            right->update(L, u, v);
        }
    }
    ll get(int u, int i){
        if(l==r) return tree->get(i);
        else if(m>=u) return max(tree->get(i), left->get(u, i));
        else return max(tree->get(i), right->get(u, i));
    }
};
segment_tree::pointer tree;
int main(){
    #ifdef Uiharu
        if(fopen(taskname".in", "r"))
            freopen(taskname".in", "r", stdin);
    #endif // Uiharu
    read(n);
    FOR(i, 1, n) q[i].input(i);
    {
        int cnt=0;
        for(auto &t: M){
            cnt++;
            t.second=cnt;
            a[cnt]=t.first;
        }
    }
    tree=new segment_tree(1, n);
    FOR(i, 1, n){
        if(q[i].t==1){
            tree->update(line(q[i].data[0], q[i].data[1]), i, deleted_at[i]-1);
        }
    }
    FOR(i, 1, n) if(q[i].t==3){
        ll res=tree->get(i, M[q[i].data[0]]);
        if(res==-inf) puts("EMPTY SET");
        else writeln(res);
    }
}


#include <bits/stdc++.h>
using namespace std;
#define FOR(i, j, k) for(int i=(j); i<=(k); i++)
#define FFOR(i, j, k) for(int i=(j); i<(k); i++)
#define DFOR(i, j, k) for(int i=(j); i>=(k); i--)
#define bug(x) cerr<<#x<<" = "<<(x)<<'\n'
#define pb push_back
#define mp make_pair
#define setbit(s, i) (s|=(1LL<<(i)))
#define bit(s, i) (((s)>>(i))&1LL)
#define mask(i) ((1LL<<(i)))
#define builtin_popcount __builtin_popcountll
using ll=long long;
using ld=long double;
template <typename T> inline void read(T &x){
    char c;
    bool nega=0;
    while((!isdigit(c=getchar()))&&(c!='-'));
    if(c=='-'){
        nega=1;
        c=getchar();
    }
    x=c-48;
    while(isdigit(c=getchar())) x=x*10+c-48;
    if(nega) x=-x;
}
template <typename T> inline void writep(T x){
    if(x>9) writep(x/10);
    putchar(x%10+48);
}
template <typename T> inline void write(T x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    writep(x);
}
template <typename T> inline void writeln(T x){
    write(x);
    putchar('\n');
}
#define taskname "F"
int n;
ll ans[300001];
const ll inf=mask(62);
int deleted_at[300001];
ll a[300001];
map <ll, int> M;
class query{
public:
    int t, id;
    vector <ll> data;
    void input(int id){
        this->id=id;
        read(t);
        data.resize(1+(t==1));
        for(ll &x: data) read(x);
        if(t==1) deleted_at[id]=n+1;
        else if(t==2) deleted_at[data[0]]=id;
        else if(t==3){
            ans[id]=-inf;
            M[data[0]]=0;
        }
    }
} q[300001];
class line{
public:
    ll a, b;
    line(ll a, ll b){
        this->a=a;
        this->b=b;
    }
    line(){
        a=0;
        b=-inf;
    }
    ll at(ll x){
        return a*x+b;
    }
};
class linear_segment_tree{
public:
    using pointer=linear_segment_tree*;
    line L;
    int l, r, m;
    pointer left, right;
    linear_segment_tree(int l, int r){
        this->l=l;
        this->r=r;
        m=(l+r)/2;
        L=line();
        left=right=nullptr;
    }
    ~linear_segment_tree(){
        if(left!=nullptr){
            delete left;
            delete right;
        }
    }
    void update(line A){
        bool gl=A.at(a[l])>=L.at(a[l]);
        bool gr=A.at(a[r])>=L.at(a[r]);
        if(gl&&gr){
            L=A;
            return;
        }
        else if(l!=r){
            if(left==nullptr){
                left=new linear_segment_tree(l, m);
                right=new linear_segment_tree(m+1, r);
            }
            left->update(A);
            right->update(A);
        }
    }
    ll get(int u){
        ll res=L.at(a[u]);
        if(l!=r){
            if(left!=nullptr){
                if(m>=u) res=max(res, left->get(u));
                else res=max(res, right->get(u));
            }
        }
        return res;
    }
};
class segment_tree{
public:
    using pointer=segment_tree*;
    vector <pair <int, int> > q;
    vector <line> A;
    int l, r, m;
    pointer left, right;
    segment_tree(int l, int r){
        this->l=l;
        this->r=r;
        m=(l+r)/2;
        if(l!=r){
            left=new segment_tree(l, m);
            right=new segment_tree(m+1, r);
        }
        else left=right=nullptr;
    }
    void update(line L, int u, int v){
        if(l>v||r<u) return;
        if(u<=l&&v>=r) A.pb(L);
        else{
            left->update(L, u, v);
            right->update(L, u, v);
        }
    }
    void mark(int u, int i){
        q.pb(mp(u, i));
        if(l!=r){
            if(m>=u) left->mark(u, i);
            else right->mark(u, i);
        }
    }
    void solve(){
        linear_segment_tree::pointer tree=new linear_segment_tree(1, M.size());
        for(line L: A) tree->update(L);
        for(pair <int, int> p: q) ans[p.first]=max(ans[p.first], tree->get(p.second));
        delete tree;
        if(left!=nullptr){
            left->solve();
            right->solve();
        }
    }
};
segment_tree::pointer tree;
int main(){
    #ifdef Uiharu
        if(fopen(taskname".in", "r"))
            freopen(taskname".in", "r", stdin);
    #endif // Uiharu
    read(n);
    FOR(i, 1, n) q[i].input(i);
    {
        int cnt=0;
        for(auto &t: M){
            cnt++;
            t.second=cnt;
            a[cnt]=t.first;
        }
    }
    tree=new segment_tree(1, n);
    FOR(i, 1, n){
        if(q[i].t==1) tree->update(line(q[i].data[0], q[i].data[1]), i, deleted_at[i]-1);
        else if(q[i].t==3) tree->mark(i, M[q[i].data[0]]);
    }
    tree->solve();
    FOR(i, 1, n) if(q[i].t==3) writeln(ans[i]);
}


#include <bits/stdc++.h>
using namespace std;
#define FOR(i, j, k) for(int i=(j); i<=(k); i++)
#define FFOR(i, j, k) for(int i=(j); i<(k); i++)
#define DFOR(i, j, k) for(int i=(j); i>=(k); i--)
#define bug(x) cerr<<#x<<" = "<<(x)<<'\n'
#define pb push_back
#define mp make_pair
#define setbit(s, i) (s|=(1LL<<(i)))
#define bit(s, i) (((s)>>(i))&1LL)
#define mask(i) ((1LL<<(i)))
#define builtin_popcount __builtin_popcountll
using ll=long long;
using ld=long double;
template <typename T> inline void read(T &x){
    char c;
    bool nega=0;
    while((!isdigit(c=getchar()))&&(c!='-'));
    if(c=='-'){
        nega=1;
        c=getchar();
    }
    x=c-48;
    while(isdigit(c=getchar())) x=x*10+c-48;
    if(nega) x=-x;
}
template <typename T> inline void writep(T x){
    if(x>9) writep(x/10);
    putchar(x%10+48);
}
template <typename T> inline void write(T x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    writep(x);
}
template <typename T> inline void writeln(T x){
    write(x);
    putchar('\n');
}
#define taskname "F"
int n;
ll ans[300001];
const ll inf=mask(62);
int deleted_at[300001];
ll a[300001];
map <ll, int> M;
class query{
public:
    int t, id;
    vector <ll> data;
    void input(int id){
        this->id=id;
        read(t);
        data.resize(1+(t==1));
        for(ll &x: data) read(x);
        if(t==1) deleted_at[id]=n+1;
        else if(t==2) deleted_at[data[0]]=id;
        else if(t==3){
            ans[id]=-inf;
            M[data[0]]=0;
        }
    }
} q[300001];
class line{
public:
    ll a, b;
    line(ll a, ll b){
        this->a=a;
        this->b=b;
    }
    line(){
        a=0;
        b=-inf;
    }
    ll at(ll x){
        return a*x+b;
    }
};
class linear_segment_tree{
public:
    using pointer=linear_segment_tree*;
    line L;
    int l, r, m;
    pointer left, right;
    linear_segment_tree(int l, int r){
        this->l=l;
        this->r=r;
        m=(l+r)/2;
        L=line();
        left=right=nullptr;
    }
    void update(line A){
        bool gl=A.at(a[l])>=L.at(a[l]);
        bool gr=A.at(a[r])>=L.at(a[r]);
        if(gl&&gr){
            L=A;
            return;
        }
        else if(l!=r){
            if(!gl&&!gr) return;
            if(left==nullptr){
                left=new linear_segment_tree(l, m);
                right=new linear_segment_tree(m+1, r);
            }
            left->update(A);
            right->update(A);
        }
    }
    ll get(int u){
        ll res=L.at(a[u]);
        if(l!=r){
            if(left!=nullptr){
                if(m>=u) res=max(res, left->get(u));
                else res=max(res, right->get(u));
            }
        }
        return res;
    }
};
class segment_tree{
public:
    using pointer=segment_tree*;
    linear_segment_tree::pointer tree;
    int l, r, m;
    pointer left, right;
    segment_tree(int l, int r){
        tree=new linear_segment_tree(1, M.size());
        this->l=l;
        this->r=r;
        m=(l+r)/2;
        if(l!=r){
            left=new segment_tree(l, m);
            right=new segment_tree(m+1, r);
        }
        else left=right=nullptr;
    }
    void update(line L, int u, int v){
        if(l>v||r<u) return;
        if(u<=l&&v>=r) tree->update(L);
        else{
            left->update(L, u, v);
            right->update(L, u, v);
        }
    }
    ll get(int u, int i){
        if(l==r) return tree->get(i);
        else if(m>=u) return max(tree->get(i), left->get(u, i));
        else return max(tree->get(i), right->get(u, i));
    }
};
segment_tree::pointer tree;
int main(){
    #ifdef Uiharu
        if(fopen(taskname".in", "r"))
            freopen(taskname".in", "r", stdin);
    #endif // Uiharu
    read(n);
    FOR(i, 1, n) q[i].input(i);
    {
        int cnt=0;
        for(auto &t: M){
            cnt++;
            t.second=cnt;
            a[cnt]=t.first;
        }
    }
    tree=new segment_tree(1, n);
    FOR(i, 1, n){
        if(q[i].t==1){
            tree->update(line(q[i].data[0], q[i].data[1]), i, deleted_at[i]-1);
        }
    }
    FOR(i, 1, n) if(q[i].t==3){
        ll res=tree->get(i, M[q[i].data[0]]);
        if(res==-inf) puts("EMPTY SET");
        else writeln(res);
    }
}


#include <bits/stdc++.h>
using namespace std;
#define FOR(i, j, k) for(int i=(j); i<=(k); i++)
#define FFOR(i, j, k) for(int i=(j); i<(k); i++)
#define DFOR(i, j, k) for(int i=(j); i>=(k); i--)
#define bug(x) cerr<<#x<<" = "<<(x)<<'\n'
#define pb push_back
#define mp make_pair
#define setbit(s, i) (s|=(1LL<<(i)))
#define bit(s, i) (((s)>>(i))&1LL)
#define mask(i) ((1LL<<(i)))
#define builtin_popcount __builtin_popcountll
using ll=long long;
using ld=long double;
template <typename T> inline void read(T &x){
    char c;
    bool nega=0;
    while((!isdigit(c=getchar()))&&(c!='-'));
    if(c=='-'){
        nega=1;
        c=getchar();
    }
    x=c-48;
    while(isdigit(c=getchar())) x=x*10+c-48;
    if(nega) x=-x;
}
template <typename T> inline void writep(T x){
    if(x>9) writep(x/10);
    putchar(x%10+48);
}
template <typename T> inline void write(T x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    writep(x);
}
template <typename T> inline void writeln(T x){
    write(x);
    putchar('\n');
}
#define taskname "F"
int n;
ll ans[300001];
const ll inf=mask(62);
int deleted_at[300001];
ll a[300001];
map <ll, int> M;
class query{
public:
    int t, id;
    vector <ll> data;
    void input(int id){
        this->id=id;
        read(t);
        data.resize(1+(t==1));
        for(ll &x: data) read(x);
        if(t==1) deleted_at[id]=n+1;
        else if(t==2) deleted_at[data[0]]=id;
        else if(t==3){
            ans[id]=-inf;
            M[data[0]]=0;
        }
    }
} q[300001];
class line{
public:
    ll a, b;
    line(ll a, ll b){
        this->a=a;
        this->b=b;
    }
    line(){
        a=0;
        b=-inf;
    }
    ll at(ll x){
        return a*x+b;
    }
};
class linear_segment_tree{
public:
    using pointer=linear_segment_tree*;
    line L;
    int l, r, m;
    pointer left, right;
    linear_segment_tree(int l, int r){
        this->l=l;
        this->r=r;
        m=(l+r)/2;
        L=line();
        left=right=nullptr;
    }
    ~linear_segment_tree(){
        if(left!=nullptr){
            delete left;
            delete right;
        }
    }
    void update(line A){
        bool gl=A.at(a[l])>=L.at(a[l]);
        bool gr=A.at(a[r])>=L.at(a[r]);
        if(gl&&gr){
            L=A;
            return;
        }
        else if(l!=r){
            if(left==nullptr){
                left=new linear_segment_tree(l, m);
                right=new linear_segment_tree(m+1, r);
            }
            left->update(A);
            right->update(A);
        }
    }
    ll get(int u){
        ll res=L.at(a[u]);
        if(l!=r){
            if(left!=nullptr){
                if(m>=u) res=max(res, left->get(u));
                else res=max(res, right->get(u));
            }
        }
        return res;
    }
};
class segment_tree{
public:
    using pointer=segment_tree*;
    vector <pair <int, int> > q;
    vector <line> A;
    int l, r, m;
    pointer left, right;
    segment_tree(int l, int r){
        this->l=l;
        this->r=r;
        m=(l+r)/2;
        if(l!=r){
            left=new segment_tree(l, m);
            right=new segment_tree(m+1, r);
        }
        else left=right=nullptr;
    }
    void update(line L, int u, int v){
        if(l>v||r<u) return;
        if(u<=l&&v>=r) A.pb(L);
        else{
            left->update(L, u, v);
            right->update(L, u, v);
        }
    }
    void mark(int u, int i){
        q.pb(mp(u, i));
        if(l!=r){
            if(m>=u) left->mark(u, i);
            else right->mark(u, i);
        }
    }
    void solve(){
        linear_segment_tree::pointer tree=new linear_segment_tree(1, M.size());
        for(line L: A) tree->update(L);
        for(pair <int, int> p: q) ans[p.first]=max(ans[p.first], tree->get(p.second));
        delete tree;
        if(left!=nullptr){
            left->solve();
            right->solve();
        }
    }
};
segment_tree::pointer tree;
int main(){
    #ifdef Uiharu
        if(fopen(taskname".in", "r"))
            freopen(taskname".in", "r", stdin);
    #endif // Uiharu
    read(n);
    FOR(i, 1, n) q[i].input(i);
    {
        int cnt=0;
        for(auto &t: M){
            cnt++;
            t.second=cnt;
            a[cnt]=t.first;
        }
    }
    tree=new segment_tree(1, n);
    FOR(i, 1, n){
        if(q[i].t==1) tree->update(line(q[i].data[0], q[i].data[1]), i, deleted_at[i]-1);
        else if(q[i].t==3) tree->mark(i, M[q[i].data[0]]);
    }
    tree->solve();
    FOR(i, 1, n) if(q[i].t==3){
        if(ans[i]==-inf) puts("EMPTY SET");
        else writeln(ans[i]);
    }
}


#include <bits/stdc++.h>
using namespace std;
#define FOR(i, j, k) for(int i=(j); i<=(k); i++)
#define FFOR(i, j, k) for(int i=(j); i<(k); i++)
#define DFOR(i, j, k) for(int i=(j); i>=(k); i--)
#define bug(x) cerr<<#x<<" = "<<(x)<<'\n'
#define pb push_back
#define mp make_pair
#define setbit(s, i) (s|=(1LL<<(i)))
#define bit(s, i) (((s)>>(i))&1LL)
#define mask(i) ((1LL<<(i)))
#define builtin_popcount __builtin_popcountll
using ll=long long;
using ld=long double;
template <typename T> inline void read(T &x){
    char c;
    bool nega=0;
    while((!isdigit(c=getchar()))&&(c!='-'));
    if(c=='-'){
        nega=1;
        c=getchar();
    }
    x=c-48;
    while(isdigit(c=getchar())) x=x*10+c-48;
    if(nega) x=-x;
}
template <typename T> inline void writep(T x){
    if(x>9) writep(x/10);
    putchar(x%10+48);
}
template <typename T> inline void write(T x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    writep(x);
}
template <typename T> inline void writeln(T x){
    write(x);
    putchar('\n');
}
#define taskname "F"
int n;
ll ans[300001];
const ll inf=mask(62);
int deleted_at[300001];
ll a[300001];
map <ll, int> M;
class query{
public:
    int t, id;
    vector <ll> data;
    void input(int id){
        this->id=id;
        read(t);
        data.resize(1+(t==1));
        for(ll &x: data) read(x);
        if(t==1) deleted_at[id]=n+1;
        else if(t==2) deleted_at[data[0]]=id;
        else if(t==3){
            ans[id]=-inf;
            M[data[0]]=0;
        }
    }
} q[300001];
class line{
public:
    ll a, b;
    line(ll a, ll b){
        this->a=a;
        this->b=b;
    }
    line(){
        a=0;
        b=-inf;
    }
    ll at(ll x){
        return a*x+b;
    }
};
class linear_segment_tree{
public:
    using pointer=linear_segment_tree*;
    line L;
    int l, r, m;
    pointer left, right;
    linear_segment_tree(int l, int r){
        this->l=l;
        this->r=r;
        m=(l+r)/2;
        L=line();
        left=right=nullptr;
    }
    ~linear_segment_tree(){
        if(left!=nullptr){
            delete left;
            delete right;
        }
    }
    void update(line A){
        bool gl=A.at(a[l])>=L.at(a[l]);
        bool gr=A.at(a[r])>=L.at(a[r]);
        if(gl&&gr){
            L=A;
            return;
        }
        else if(l!=r){
            if(!gl&&!gr) return;
            if(left==nullptr){
                left=new linear_segment_tree(l, m);
                right=new linear_segment_tree(m+1, r);
            }
            left->update(A);
            right->update(A);
        }
    }
    ll get(int u){
        ll res=L.at(a[u]);
        if(l!=r){
            if(left!=nullptr){
                if(m>=u) res=max(res, left->get(u));
                else res=max(res, right->get(u));
            }
        }
        return res;
    }
};
class segment_tree{
public:
    using pointer=segment_tree*;
    vector <pair <int, int> > q;
    vector <line> A;
    int l, r, m;
    pointer left, right;
    segment_tree(int l, int r){
        this->l=l;
        this->r=r;
        m=(l+r)/2;
        if(l!=r){
            left=new segment_tree(l, m);
            right=new segment_tree(m+1, r);
        }
        else left=right=nullptr;
    }
    void update(line L, int u, int v){
        if(l>v||r<u) return;
        if(u<=l&&v>=r) A.pb(L);
        else{
            left->update(L, u, v);
            right->update(L, u, v);
        }
    }
    void mark(int u, int i){
        q.pb(mp(u, i));
        if(l!=r){
            if(m>=u) left->mark(u, i);
            else right->mark(u, i);
        }
    }
    void solve(){
        linear_segment_tree::pointer tree=new linear_segment_tree(1, M.size());
        for(line L: A) tree->update(L);
        for(pair <int, int> p: q) ans[p.first]=max(ans[p.first], tree->get(p.second));
        delete tree;
        if(left!=nullptr){
            left->solve();
            right->solve();
        }
    }
};
segment_tree::pointer tree;
int main(){
    #ifdef Uiharu
        if(fopen(taskname".in", "r"))
            freopen(taskname".in", "r", stdin);
    #endif // Uiharu
    read(n);
    FOR(i, 1, n) q[i].input(i);
    {
        int cnt=0;
        for(auto &t: M){
            cnt++;
            t.second=cnt;
            a[cnt]=t.first;
        }
    }
    tree=new segment_tree(1, n);
    FOR(i, 1, n){
        if(q[i].t==1) tree->update(line(q[i].data[0], q[i].data[1]), i, deleted_at[i]-1);
        else if(q[i].t==3) tree->mark(i, M[q[i].data[0]]);
    }
    tree->solve();
    FOR(i, 1, n) if(q[i].t==3){
        if(ans[i]==-inf) puts("EMPTY SET");
        else writeln(ans[i]);
    }
}


#include <bits/stdc++.h>
using namespace std;
#define FOR(i, j, k) for(int i=(j); i<=(k); i++)
#define FFOR(i, j, k) for(int i=(j); i<(k); i++)
#define DFOR(i, j, k) for(int i=(j); i>=(k); i--)
#define bug(x) cerr<<#x<<" = "<<(x)<<'\n'
#define pb push_back
#define mp make_pair
#define setbit(s, i) (s|=(1LL<<(i)))
#define bit(s, i) (((s)>>(i))&1LL)
#define mask(i) ((1LL<<(i)))
#define builtin_popcount __builtin_popcountll
using ll=long long;
using ld=long double;
template <typename T> inline void read(T &x){
    char c;
    bool nega=0;
    while((!isdigit(c=getchar()))&&(c!='-'));
    if(c=='-'){
        nega=1;
        c=getchar();
    }
    x=c-48;
    while(isdigit(c=getchar())) x=x*10+c-48;
    if(nega) x=-x;
}
template <typename T> inline void writep(T x){
    if(x>9) writep(x/10);
    putchar(x%10+48);
}
template <typename T> inline void write(T x){
    if(x<0){
        putchar('-');
        x=-x;
    }
    writep(x);
}
template <typename T> inline void writeln(T x){
    write(x);
    putchar('\n');
}
#define taskname "F"
int n;
ll ans[300001];
const ll inf=mask(62);
int deleted_at[300001];
ll a[300001];
map <ll, int> M;
class query{
public:
    int t, id;
    vector <ll> data;
    void input(int id){
        this->id=id;
        read(t);
        data.resize(1+(t==1));
        for(ll &x: data) read(x);
        if(t==1) deleted_at[id]=n+1;
        else if(t==2) deleted_at[data[0]]=id;
        else if(t==3){
            ans[id]=-inf;
            M[data[0]]=0;
        }
    }
} q[300001];
class line{
public:
    ll a, b;
    line(ll a, ll b){
        this->a=a;
        this->b=b;
    }
    line(){
        a=0;
        b=-inf;
    }
    ll at(ll x){
        return a*x+b;
    }
};
class linear_segment_tree{
public:
    using pointer=linear_segment_tree*;
    line L;
    pointer left, right;
    linear_segment_tree(){
        L=line();
        left=right=nullptr;
    }
    void update(line A, int l, int r){
        int m=(l+r)/2;
        bool gl=A.at(a[l])>=L.at(a[l]);
        bool gr=A.at(a[r])>=L.at(a[r]);
        if(gl&&gr){
            L=A;
            return;
        }
        else if(l!=r){
            if(left==nullptr){
                left=new linear_segment_tree();
                right=new linear_segment_tree();
            }
            left->update(A, l, m);
            right->update(A, m+1, r);
        }
    }
    ll get(int u, int l, int r){
        int m=(l+r)/2;
        ll res=L.at(a[u]);
        if(l!=r){
            if(left!=nullptr){
                if(m>=u) res=max(res, left->get(u, l, m));
                else res=max(res, right->get(u, m+1, r));
            }
        }
        return res;
    }
};
class segment_tree{
public:
    using pointer=segment_tree*;
    linear_segment_tree::pointer tree;
    int l, r, m;
    pointer left, right;
    segment_tree(int l, int r){
        tree=new linear_segment_tree();
        this->l=l;
        this->r=r;
        m=(l+r)/2;
        if(l!=r){
            left=new segment_tree(l, m);
            right=new segment_tree(m+1, r);
        }
        else left=right=nullptr;
    }
    void update(line L, int u, int v){
        if(l>v||r<u) return;
        if(u<=l&&v>=r) tree->update(L, 1, M.size());
        else{
            left->update(L, u, v);
            right->update(L, u, v);
        }
    }
    ll get(int u, int i){
        if(l==r) return tree->get(i, 1, M.size());
        else if(m>=u) return max(tree->get(i, 1, M.size()), left->get(u, i));
        else return max(tree->get(i, 1, M.size()), right->get(u, i));
    }
};
segment_tree::pointer tree;
int main(){
    #ifdef Uiharu
        if(fopen(taskname".in", "r"))
            freopen(taskname".in", "r", stdin);
    #endif // Uiharu
    read(n);
    FOR(i, 1, n) q[i].input(i);
    {
        int cnt=0;
        for(auto &t: M){
            cnt++;
            t.second=cnt;
            a[cnt]=t.first;
        }
    }
    tree=new segment_tree(1, n);
    FOR(i, 1, n){
        if(q[i].t==1){
            tree->update(line(q[i].data[0], q[i].data[1]), i, deleted_at[i]-1);
        }
    }
    FOR(i, 1, n) if(q[i].t==3){
        ll res=tree->get(i, M[q[i].data[0]]);
        if(res==-inf) puts("EMPTY SET");
        else writeln(res);
    }
}


#include<bits/stdc++.h>
using namespace std;

// Numeric Constants
#define N 1000000007
#define maxs 300005
#define mins 1005
#define eps 1e-14
#define imax 2000000200
#define llmax 1000000002000000000ll
#define pi 3.141592653589793

// Others
#define ll long long
#define pb push_back
#define gc getchar_unlocked
#define iosbase ios_base::sync_with_stdio(false)
#define pii pair<int,int>
#define pll pair<ll,ll>
#define ppi pair<pair<int,int>,int>
#define ppl pair<pll,ll>
#define vi vector<int>
#define sc scanf
#define pr printf
#define lld I64d
#define F first
#define S second
#define siter set<int>::iterator
#define p_pq priority_queue
#define ub upper_bound
#define lb lower_bound
#define mps make_pair

vector<ppi>arr;
pii p[maxs];
vector<pii>quers;
vector<ppi>v;
int mark[maxs],type[maxs],q[maxs],id[maxs];

bool fun(ppi p1,ppi p2,ppi p3){
	double d1=(double)(p3.F.S-p2.F.S)/(p2.F.F-p3.F.F);
	double d2=(double)(p1.F.S-p2.F.S)/(p2.F.F-p1.F.F);
	return d1<=d2;
}

bool comp(ppi p1,ppi p2){
	if(p1.F.F<p2.F.F){
		return true;
	}
	else if(p1.F.F > p2.F.F){
		return false;
	}
	return p1.F.S > p2.F.S;
}

void convex(){
	int i,j;
	sort(arr.begin(),arr.end(),comp);
	int n=arr.size();
	v.clear();
	for(i=0;i<n;i++){
		if(i>0 && abs(arr[i-1].F.F-arr[i].F.F) <= eps){
			continue;
		}
		if(mark[arr[i].S]==1){
			continue;
		}
		//cout<<arr[i].S<<" "<<arr[i].F.F<<" "<<arr[i].F.S<<" "<<"Done"<<endl;
		while(v.size()>=2 && fun(v[v.size()-2],v[v.size()-1],arr[i])) v.pop_back();
		v.push_back(arr[i]);
	}
}
ll ans[maxs];
void solve()
{
	int i,lo=0;
	sort(quers.begin(),quers.end());
	//cout<<v.size()<<" "<<quers.size()<<" "<<"Hello"<<endl;
	for(i=0;i<quers.size();i++){
		while((lo+1)<v.size()){
			pii p2=v[lo].F,p3=v[lo+1].F;
			double d1=(double)(p3.S-p2.S)/(p2.F-p3.F);
			if(d1<(double)quers[i].F+eps){
				lo++;
			}
			else{
				break;
			}
		}
		if(lo<v.size())
			ans[quers[i].S]=max(ans[quers[i].S],(ll)quers[i].F*v[lo].F.F+v[lo].F.S);
	}
}

int main()
{
	int n,i,j,k,t;
	sc("%d",&n);
	for(i=0;i<n;i++){
		sc("%d",&t);
		type[i]=t;
		if(t==1){
			sc("%d %d",&p[i].F,&p[i].S);
		}
		else if(t==2){
			sc("%d",&id[i]);
			id[i]--;
		}
		else{
			sc("%d",&q[i]);
		}
	}
	for(i=0;i<n;i++){
		ans[i]=-llmax;
	}
	int blck=sqrt(n);
	for(j=0;j<n;j++){
		mark[j]=0;
	}
	for(i=0;i<n;i+=blck){
		int lo=min(n-1,i+blck-1);
		for(j=i;j<=lo;j++){
			if(type[j]==2){
				mark[id[j]]=1;
			}
		}
		quers.clear();
		for(j=i;j<=lo;j++){
			if(type[j]==3){
				quers.pb(mps(q[i],i));
			}
		}
		convex();
		solve();
		for(j=i;j<=lo;j++){
			if(type[j]==2){
				mark[id[j]]=0;
			}
		}
		for(j=i;j<=lo;j++){
			if(type[j]==2){
				mark[id[j]]=1;
			}
			else if(type[j]==3){
				for(int p1=lo;p1>=i;p1--){
					if(p1<=j && mark[p1]==0 && type[p1]==1){
						ans[j]=max(ans[j],(ll)p[p1].F*q[j]+p[p1].S);
					}
					else if(p1>j && type[p1]==2 && id[p1]<i){
						int ind=id[p1];
					//	cout<<ans[j]<<endl;
						ans[j]=max(ans[j],(ll)p[ind].F*q[j]+p[ind].S);
					//	cout<<i<<" "<<j<<" "<<ind<<" "<<ans[j]<<" "<<q[j]<<endl;
					}
				}
			}
		}
		for(j=i;j<=lo;j++){
			if(mark[j]==0 && type[j]==1){
				arr.pb(mps(p[j],j));
			}
		}
	}
	for(i=0;i<n;i++){
		if(type[i]==3){
			if(ans[i]<=-llmax){
				pr("EMPTY SET\n");
			}
			else{
				pr("%lld\n",ans[i]);
			}
		}
	}
	return 0;
}


#include<bits/stdc++.h>
using namespace std;

// Numeric Constants
#define N 1000000007
#define maxs 300005
#define mins 1005
#define eps 1e-14
#define imax 2000000200
#define llmax 1000000002000000000ll
#define pi 3.141592653589793

// Others
#define ll long long
#define pb push_back
#define gc getchar_unlocked
#define iosbase ios_base::sync_with_stdio(false)
#define pii pair<ll,ll>
#define pll pair<ll,ll>
#define ppi pair<pair<ll,ll>,ll>
#define ppl pair<pll,ll>
#define vi vector<ll>
#define sc scanf
#define pr printf
#define lld I64d
#define F first
#define S second
#define siter set<int>::iterator
#define p_pq priority_queue
#define ub upper_bound
#define lb lower_bound
#define mps make_pair

vector<ppi>arr;
pii p[maxs];
vector<pii>quers;
vector<ppi>v;
ll mark[maxs],type[maxs],q[maxs],id[maxs];

bool fun(ppi p1,ppi p2,ppi p3){
	double d1=(double)(p3.F.S-p2.F.S)/(p2.F.F-p3.F.F);
	double d2=(double)(p1.F.S-p2.F.S)/(p2.F.F-p1.F.F);
	return d1<=d2;
}

bool comp(ppi p1,ppi p2){
	if(p1.F.F<p2.F.F){
		return true;
	}
	else if(p1.F.F > p2.F.F){
		return false;
	}
	return p1.F.S > p2.F.S;
}

void convex(){
	ll i,j;
	sort(arr.begin(),arr.end(),comp);
	ll n=arr.size();
	v.clear();
	for(i=0;i<n;i++){
		if(i>0 && abs(arr[i-1].F.F-arr[i].F.F) <= eps){
			continue;
		}
		if(mark[arr[i].S]==1){
			continue;
		}
		//cout<<arr[i].S<<" "<<arr[i].F.F<<" "<<arr[i].F.S<<" "<<"Done"<<endl;
		while(v.size()>=2 && fun(v[v.size()-2],v[v.size()-1],arr[i])) v.pop_back();
		v.push_back(arr[i]);
	}
	//cout<<arr.size()<<" "<<v.size()<<" "<<"Done\n";
}
ll ans[maxs];
void solve()
{
	ll i,lo=0;
	sort(quers.begin(),quers.end());
	//cout<<v.size()<<" "<<quers.size()<<" "<<"Hello"<<endl;
	for(i=0;i<quers.size();i++){
		while((lo+1)<v.size()){
			pii p2=v[lo].F,p3=v[lo+1].F;
			double d1=(double)(p3.S-p2.S)/(p2.F-p3.F);
			if(d1<(double)quers[i].F+eps){
				lo++;
			}
			else{
				break;
			}
		}
		//cout<<quers[i].S<<" "<<lo<<"\n";
		if(lo<v.size())
			ans[quers[i].S]=max(ans[quers[i].S],(ll)quers[i].F*v[lo].F.F+v[lo].F.S);
	}
}

int main()
{
	ll n,i,j,k,t;
	sc("%lld",&n);
	for(i=0;i<n;i++){
		sc("%lld",&t);
		type[i]=t;
		if(t==1){
			sc("%lld %lld",&p[i].F,&p[i].S);
		}
		else if(t==2){
			sc("%lld",&id[i]);
			id[i]--;
		}
		else{
			sc("%lld",&q[i]);
		}
	}
	for(i=0;i<n;i++){
		ans[i]=-llmax;
	}
	ll blck=sqrt(n);
	//cout<<blck<<endl;
	for(j=0;j<n;j++){
		mark[j]=0;
	}
	for(i=0;i<n;i+=blck){
		ll lo=min(n-1,i+blck-1);
		for(j=i;j<=lo;j++){
			if(type[j]==2){
				mark[id[j]]=1;
			}
		}
		quers.clear();
		for(j=i;j<=lo;j++){
			if(type[j]==3){
				quers.pb(mps(q[j],j));
			}
		}
		convex();
		solve();
		for(j=i;j<=lo;j++){
			if(type[j]==2){
				mark[id[j]]=0;
			}
		}
		for(j=i;j<=lo;j++){
			if(type[j]==2){
				mark[id[j]]=1;
			}
			else if(type[j]==3){
				for(ll p1=lo;p1>=i;p1--){
					if(p1<=j && mark[p1]==0 && type[p1]==1){
						ans[j]=max(ans[j],(ll)p[p1].F*q[j]+p[p1].S);
					}
					else if(p1>j && type[p1]==2 && id[p1]<i){
						ll ind=id[p1];
					//	cout<<ans[j]<<endl;
						ans[j]=max(ans[j],(ll)p[ind].F*q[j]+p[ind].S);
					//	cout<<i<<" "<<j<<" "<<ind<<" "<<ans[j]<<" "<<q[j]<<endl;
					}
				}
			}
		}
		for(j=i;j<=lo;j++){
			if(mark[j]==0 && type[j]==1){
				arr.pb(mps(p[j],j));
			}
		}
	}
	for(i=0;i<n;i++){
		if(type[i]==3){
			if(ans[i]<=-llmax){
				pr("EMPTY SET\n");
			}
			else{
				pr("%lld\n",ans[i]);
			}
		}
	}
	return 0;
}