Tavas is a cheerleader in the new sports competition named "Pashmaks".

<image>

This competition consists of two part: swimming and then running. People will immediately start running R meters after they finished swimming exactly S meters. A winner is a such person that nobody else finishes running before him/her (there may be more than one winner).

Before the match starts, Tavas knows that there are n competitors registered for the match. Also, he knows that i-th person's swimming speed is si meters per second and his/her running speed is ri meters per second. Unfortunately, he doesn't know the values of R and S, but he knows that they are real numbers greater than 0.

As a cheerleader, Tavas wants to know who to cheer up. So, he wants to know all people that might win. We consider a competitor might win if and only if there are some values of R and S such that with these values, (s)he will be a winner.

Tavas isn't really familiar with programming, so he asked you to help him.

Input

The first line of input contains a single integer n (1 ≤ n ≤ 2 × 105).

The next n lines contain the details of competitors. i-th line contains two integers si and ri (1 ≤ si, ri ≤ 104).

Output

In the first and the only line of output, print a sequence of numbers of possible winners in increasing order.

Examples

Input

3
1 3
2 2
3 1


Output

1 2 3 


Input

3
1 2
1 1
2 1


Output

1 3 
5
10 50
10 50
10 50
10 50
10 50
 2
10000 10000
10000 10000
 3
10000 10000
10000 10000
10000 10000
 3
1000 3000
1500 1500
3000 1000
 43
75 16
70 7
75 16
54 2
70 7
54 2
70 7
54 2
70 7
54 2
54 2
70 7
70 7
54 2
70 7
75 16
70 7
54 2
54 2
54 2
54 2
54 2
54 2
75 16
70 7
70 7
54 2
70 7
75 16
54 2
75 16
75 16
54 2
54 2
70 7
70 7
75 16
70 7
70 7
70 7
75 16
75 16
54 2
 1
1 1
 2
1 1
1 1
 44
78 52
75 16
70 7
75 16
54 2
70 7
54 2
70 7
54 2
70 7
54 2
54 2
70 7
70 7
54 2
70 7
75 16
70 7
54 2
54 2
54 2
54 2
54 2
54 2
75 16
70 7
70 7
54 2
70 7
75 16
54 2
75 16
75 16
54 2
54 2
70 7
70 7
75 16
70 7
70 7
70 7
75 16
75 16
54 2
 3
1000 3000
1499 1499
3000 1000
 5
50 50
49 50
50 49
49 49
50 1
 18
82 38
33 69
33 69
33 69
33 69
33 69
82 38
33 69
33 69
33 69
82 38
33 69
33 69
82 38
82 38
33 69
33 69
33 69
 1
10000 9999
 3
1000 3000
1501 1501
3000 1000
 2
1 2
2 1

1 2 3 4 5
 1 2
 1 2 3
 1 2 3
 1 3 16 24 29 31 32 37 41 42
 1
 1 2
 1
 1 3
 1
 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18
 1
 1 2 3
 1 2 

import java.util.*;
import java.io.*;

public class runswim {
	
	private static final int INF = (int)1e9;
	private static class PtD implements Comparable<PtD>{
		public static final double EPS = 1e-9;
		double x, y;
		/* add hashCode() and equals() if needed */
		PtD(double x, double y) {
			this.x = x;
			this.y = y;
		}
		public double dist(PtD p) {
			return Math.sqrt(distSquared(p));
		}
		public double distSquared(PtD p) {
			double dx = x - p.x;
			double dy = y - p.y;
			return dx * dx + dy * dy;
		}
		// For debugging.
		public String toString(){
			return "(" + x + "," + y + ")";
		}
		public int compareTo(PtD p2) {
			if (Math.abs(y - p2.y) < EPS) {
				if (Math.abs(x - p2.x) < EPS)
					return 0;
				if (x < p2.x)
					return -1;
				return 1;
			}
			if (y < p2.y)
				return -1;
			return 1;
		}
		public int compareTo(PtD p2, PtD pivot) {
			if (Math.abs(y - pivot.y) < EPS && Math.abs(y - p2.y) < EPS) {
				if (Math.abs(x - p2.x) < EPS)
					return 0;
				if (x > p2.x) // !!
					return -1;
				return 1;
			}
			double k = sub(pivot).cross(p2.sub(pivot));
			if (Math.abs(k) < EPS) {
				double d = distSquared(pivot) - p2.distSquared(pivot);
				if (Math.abs(d) < EPS)
					return 0;
				if (d < 0)
					return -1;
				return 1;
			}
			if (k < 0)
				return -1;
			return 1;
		}
		public PtD sub(PtD p2) {
			return new PtD(x - p2.x, y - p2.y);
		}
		public double dot(PtD p2) {
			return x * p2.x + y * p2.y;
		}
		public double cross(PtD p2) {
			return x * p2.y - p2.x * y;
		}
		/* centroid - they must be in order
		 * (CW or CCW, does not matter)
		 */
		public static PtD centroid(PtD[] p, int n) {
			PtD c = new PtD(0, 0);
			int i, j;
			double sum = 0;
			double area = 0;
			for (i = n - 1, j = 0; j < n; i = j++) {
				area = p[i].x * p[j].y - p[i].y * p[j].x;
				sum += area;
				c.x += (p[i].x + p[j].x) * area;
				c.y += (p[i].y + p[j].y) * area;
			}
			sum *= 3.0;
			c.x /= sum;
			c.y /= sum;
			return c;
		}
		/* signed area of a polygon */
		public static double signedArea(PtD[] p, int n) {
			double sum = 0;
			for (int i = n - 1, j = 0; j < n; i = j++) {
				sum += p[i].x * p[j].y - p[i].y * p[j].x;
			}
			return 0.5 * sum;
		}
		/**
		 * Circle through three points
		 *
		 * @return a[]={x,y,r}, null if colinear
		 */
		public static double[] circleThroughThreePoints(PtD A, PtD B, PtD C) {
			double[] a = new double[3];
			double area = 0.5 * ((B.x - A.x) * (C.y - A.y) - (C.x - A.x)
					* (B.y - A.y));
			if (Math.abs(area) < EPS)
				return null;
			double lbaSqr = (B.x - A.x) * (B.x - A.x) + (B.y - A.y) * (B.y - A.y);
			double lcaSqr = (C.x - A.x) * (C.x - A.x) + (C.y - A.y) * (C.y - A.y);
			a[0] = A.x + ((C.y - A.y) * lbaSqr - ((B.y - A.y) * lcaSqr))
					/ (4 * area);
			a[1] = A.y + ((B.x - A.x) * lcaSqr - ((C.x - A.x) * lbaSqr))
					/ (4 * area);
			a[2] = Math.sqrt((a[0] - A.x) * (a[0] - A.x) + (a[1] - A.y)
					* (a[1] - A.y));
			return a;
		}
		/**
		 * Intersection of circles. PtD needs sub[traction](), dot() and EPS defined
		 *
		 * @param p0
		 * Center of 1st circle
		 * @param p1
		 * Center of 2nd circle
		 * @param r0
		 * radius of 1st circle
		 * @param r1
		 * radius of 2nd circle
		 * @param a
		 * array that will hold the points (if any)
		 * @return number of intersection points (-1 means infinity)
		 */
		public static int circleIntersection(PtD p0, PtD p1, double r0, double r1,
				PtD[] a) {
			PtD U = p1.sub(p0);
			PtD V = new PtD(U.y, -U.x);
			double duSqr = U.dot(U);
			double du = Math.sqrt(duSqr);
			if (Math.abs(U.x) < EPS && Math.abs(U.y) < EPS
					&& Math.abs(r0 - r1) < EPS) {
				return -1; // same circles
			}
			if (Math.abs(du - (r0 + r1)) < EPS) {
				// one point from outside
				double cc = r0 / (r0 + r1);
				a[0] = new PtD(p0.x + cc * U.x, p0.y + cc * U.y);
				return 1;
			}
			if (Math.abs(du - Math.abs(r0 - r1)) < EPS) {
				// one point from inside
				double cc = r0 / (r0 - r1);
				a[0] = new PtD(p0.x + cc * U.x, p0.y + cc * U.y);
				return 1;
			}
			if (du - Math.abs(r0 - r1) >= EPS && (r0 + r1) - du >= EPS) {
				// two points
				double s = 0.5 * ((r0 * r0 - r1 * r1) / duSqr + 1);
				double t = Math.sqrt(r0 * r0 / duSqr - s * s);
				a[0] = new PtD(p0.x + s * U.x + t * V.x, p0.y + s * U.y + t * V.y);
				a[1] = new PtD(p0.x + s * U.x - t * V.x, p0.y + s * U.y - t * V.y);
				return 2;
			}
			// no intersection
			return 0;
		}
		/**
		 * @param ps
		 * array containing the set of distinct points
		 * @param n
		 * number of points
		 * @return array of points on the convex hull (may be empty, if n<=0)
		 */
		public static PtD[] grahamScan(PtD[] ps, int n, boolean keepColinear) {
			// maybe check for these outside?
			if (n <= 0) {
				PtD[] ret = new PtD[0];
				return ret; // or null?
			}
			if (n == 1) {
				PtD[] ret = new PtD[1];
				ret[0] = ps[0];
				return ret;
			}
			// find pivot and sort
			int p = 0;
			for (int i = 1; i < n; i++) {
				if (ps[i].compareTo(ps[p]) < 0)
					p = i;
			}
			PtD tmp = ps[0];
			ps[0] = ps[p];
			ps[p] = tmp;
			angularSort(ps, 1, n);
			// check if they are all on the same line
			if (Math.abs((ps[n - 1].sub(ps[0])).cross(ps[1].sub(ps[0]))) < EPS) {
				if (keepColinear) {
					PtD[] ret = new PtD[n];
					ret[0] = ps[0];
					if (ps[0].distSquared(ps[1]) >= ps[0].distSquared(ps[n - 1])
							+ EPS)
						for (int i = 1; i < n; i++)
							ret[n - i] = ps[i];
					else
						for (int i = 1; i < n; i++)
							ret[i] = ps[i];
					return ret;
				} else {
					PtD[] ret = new PtD[2];
					ret[0] = ps[0];
					if (ps[0].distSquared(ps[1]) >= ps[0].distSquared(ps[n - 1])
							+ EPS)
						ret[1] = ps[1];
					else
						ret[1] = ps[n - 1];
					return ret;
				}
			}
			// remove closer ones on the same line
			PtD[] tps = new PtD[n];
			tps[0] = ps[0];
			tps[1] = ps[1];
			int tt = 0;
			int start = 2;
			int end = n;
			if (keepColinear) {
				PtD a = ps[0].sub(ps[1]);
				while (Math.abs(a.cross(ps[0].sub(ps[start]))) < EPS) {
					tps[start] = ps[start];
					start++;
				}
				a = ps[0].sub(ps[n - 1]);
				while (Math.abs(a.cross(ps[0].sub(ps[end - 1]))) < EPS) {
					end--;
				}
				end++;
			}
			for (int i = start; i < end; i++) {
				PtD a = tps[i - tt - 1].sub(tps[i - tt - 2]);
				PtD b = ps[i].sub(tps[i - tt - 2]);
				if (!keepColinear && Math.abs(a.cross(b)) < EPS) {
					tps[i - tt - 1] = ps[i];
					tt++;
				} else {
					tps[i - tt] = ps[i];
				}
			}
			for (int i = end; i < n; i++) {
				tps[i - tt] = ps[i];
			}
			// remove last point if colinear
			if (!keepColinear && n - tt > 2) {
				PtD a = tps[0].sub(tps[n - tt - 2]);
				PtD b = tps[0].sub(tps[n - tt - 1]);
				if (Math.abs(a.cross(b)) < EPS)
					tt++;
			}
			n -= tt;
			PtD[] stack = new PtD[n];
			int stackSize = 0;
			stack[stackSize++] = tps[0];
			stack[stackSize++] = tps[1];
			for (int i = 2; i < n; i++) {
				while (true) {
					PtD a = stack[stackSize - 1].sub(stack[stackSize - 2]);
					PtD b = tps[i].sub(stack[stackSize - 2]);
					double cross = a.cross(b);
					if (cross <= -EPS || (cross < EPS && keepColinear))
						break;
					stackSize--;
				}
				stack[stackSize++] = tps[i];
			}
			PtD[] ret = new PtD[stackSize];
			System.arraycopy(stack, 0, ret, 0, stackSize);
			return ret;
		}
		private static void angularSort(PtD ps[], int begin, int end) {
			int mid;
			if (end - begin <= 1) {
				return;
			}
			mid = (begin + end) / 2;
			angularSort(ps, begin, mid);
			angularSort(ps, mid, end);
			merge(ps, begin, mid, end);
		}
		private static void merge(PtD[] ps, int start, int mid, int end) {
			int i = start;
			int j = mid;
			int k = 0;
			PtD[] temp = new PtD[end - start];
			while ((i < mid) && (j < end))
				if (ps[i].compareTo(ps[j], ps[0]) <= 0) {
					temp[k++] = ps[i++];
				} else {
					temp[k++] = ps[j++];
				}
			while (i < mid) {
				temp[k++] = ps[i++];
			}
			while (j < end) {
				temp[k++] = ps[j++];
			}
			for (i = start; i < end; i++)
				ps[i] = temp[i - start];
		}
	}
	
	public static void main(String[] args) throws IOException {
		BufferedReader f = new BufferedReader(new InputStreamReader(System.in));
		int N = Integer.parseInt(f.readLine());
		TreeMap<PtD, Integer> M = new TreeMap<PtD, Integer>();
		PtD[] points = new PtD[N];
		for(int i=0;i<N;i++){
			StringTokenizer st = new StringTokenizer(f.readLine());
			double swim = Integer.parseInt(st.nextToken());
			double run = Integer.parseInt(st.nextToken());
			swim = 1/swim;
			run = 1/run;
			double x = swim - run;
			double y = swim + run;
			PtD p = new PtD(x,y);
			points[i] = p;
			M.put(p, i+1);
		}
		PtD[] hull = PtD.grahamScan(points, N, true);
//		for(PtD p : hull){
//			System.out.println(p);
//		}
		int m = hull.length;
		int left = 0;
		double x = Double.MAX_VALUE;
		for(int i=0;i<m;i++){
			if(hull[i].x < x){
				left = i;
				x = hull[i].x;
			}
		}
		
//		System.out.println(left);
		ArrayList<Integer> answers = new ArrayList<Integer>();
		int count = 0;
		for(int i=left;;i = (i - 1+m) % m){
			if(count != 0 && hull[(i+1)%m].x > hull[i].x) break;
			answers.add(M.get(hull[i]));
			count++;
		}
		Collections.sort(answers);
		for(int t : answers){
			System.out.print(t + " ");
		}
	}
}
