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

#define pb push_back
#define rs resize
#define mp make_pair
#define pi 3.1415926535897932384626433832795
#define sz(a) (int)(a).size()
#define Sort(a) sort((a).begin(), (a).end())
#define Reverse(a) reverse((a).begin(), (a).end())
#define sf scanf
#define pf printf
#define ms(a, x) memset((a), (x), sizeof(a))
typedef vector <int> vi;
typedef vector <vi> vvi;
typedef vector <vvi> vvvi;
typedef vector <vvvi> vvvvi;
typedef vector <bool> vb;
typedef vector <vb> vvb;
typedef vector <vvb> vvvb;
typedef vector <vvvb> vvvvb;
typedef long long ll;
typedef vector <ll> vl;
typedef vector <vl> vvl;
typedef vector <vvl> vvvl;
typedef vector <vvvl> vvvvl;
typedef pair <int, int> ii;
typedef vector <ii> vii;
typedef vector <vii> vvii;
typedef pair <int, ll> il;
typedef vector <il> vil;
typedef vector <vil> vvil;
typedef pair <ll, int> li;
typedef vector <li> vli;
typedef vector <vli> vvli;
typedef set <int> si;
typedef set <li> sli;
typedef set <il> sil;
typedef vector <string> vs;
typedef vector <vs> vvs;
typedef vector <vvs> vvvs;
typedef map <char, int> mci;
typedef pair <ll, ll> pll;
typedef vector <pll> vll;

ll gcd(ll a, ll b) {
    return b != 0 ? gcd(b, a % b) : a;
}

struct Rational {
    ll a, b;

    Rational() {}
    Rational(ll a, ll b = 1) : a(a), b(b) {
        ll d = gcd(abs(a), abs(b));
        this->a /= d;
        this->b /= d;
        if (this->b < 0) {
            this->a *= -1;
            this->b *= -1;
        }
    }

    Rational operator +(Rational other) {
        return Rational(a * other.b + b * other.a, b * other.b);
    }

    Rational operator -(Rational other) {
        return Rational(a * other.b - b * other.a, b * other.b);
    }

    Rational operator *(Rational other) {
        return Rational(a * other.a, b * other.b);
    }

    Rational operator /(Rational other) {
        return Rational(a * other.b, b * other.a);
    }

    bool operator <(Rational other) {
        return a * other.b < b * other.a;
    }

    bool operator >(Rational other) {
        return a * other.b > b * other.a;
    }

    bool operator ==(Rational other) {
        return a * other.b == b * other.a;
    }
};

ostream& operator <<(ostream& out, Rational a) {
    out << a.a << '/' << a.b;
    return out;
}

struct point {
    long double x, y;

    point() {}
    point(long double x, long double y) : x(x), y(y) {}

    point operator -(point b) {
        return point(x - b.x, y - b.y);
    }

    point operator +(point b) {
        return point(x + b.x, y + b.y);
    }

};

bool operator <(point a, point b) {
    return a.x * b.y - a.y * b.x > 0 || a.x * b.y - a.y * b.x == 0 && a.x * a.x + a.y * a.y < b.x * b.x + b.y * b.y;
}

bool operator ==(point a, point b) {
    return a.x == b.x && a.y == b.y;
}

bool operator <=(point a, point b) {
    return a < b || b == a;
}

ostream& operator <<(ostream& out, point a) {
    out << a.x << ' ' << a.y << endl;
    return out;
}

void eprint(vector <pair <point, int> > a) {
    cerr << endl;
    for (auto x: a) {
        cerr << x.first;
    }
    cerr << endl;
}

int main() {
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    ios_base::sync_with_stdio(0);
    cin.tie(0);
    int n;
    cin >> n;
    vector <pair <point, int> > a(n);
    for (int i = 0; i < n; ++i) {
        int s, r;
        cin >> s >> r;
        a[i].first.x = 1000.0 / s;
        a[i].first.y = 1000.0 / r;
        a[i].second = i + 1;
    }
    int best = 0;
    for (int i = 1; i < n; ++i) {
        if (a[i].first.x < a[best].first.x || a[i].first.x == a[best].first.x && a[i].first.y < a[best].first.y) {
            best = i;
        }
    }
    long double x = a[best].first.x, y = a[best].first.y;
    //cerr << x << ' ' << y << endl;
    for (int i = 0; i < n; ++i) {
        a[i].first = a[i].first - point(x, y);
    }
    sort(a.begin(), a.end());
    //eprint(a);
    vector <pair <point, int> > ans;
    ans.pb(a[0]);
    ans.pb(a[1]);
    for (int i = 2; i < sz(a); ++i) {
        while (sz(ans) > 1 && (a[i].first - ans.back().first) <= (ans.back().first - ans[sz(ans) - 2].first)) {
            ans.pop_back();
        }
        ans.push_back(a[i]);
    }
    //eprint(ans);
    best = 0;
    for (int i = 1; i < sz(ans); ++i) {
        if (ans[i].first.y < ans[best].first.y || ans[i].first.y == ans[best].first.y && ans[i].first.x < ans[best].first.x)
            best = i;
    }
    vector <int> result;
    for (int i = 0; i <= best; ++i) {
        result.pb(ans[i].second);
    }
    for (int i = 0; i < n; ++i) {
        if (a[i].first == ans[0].first || a[i].first == ans[best].first)
            result.pb(a[i].second);
    }
    Sort(result);
    for (int i = 0; i < sz(result); ++i) {
        if (i == 0 || result[i] != result[i - 1]) {
            cout << result[i] << ' ';
        }
    }
    return 0;
}
//


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

#define pb push_back
#define rs resize
#define mp make_pair
#define pi 3.1415926535897932384626433832795
#define sz(a) (int)(a).size()
#define Sort(a) sort((a).begin(), (a).end())
#define Reverse(a) reverse((a).begin(), (a).end())
#define sf scanf
#define pf printf
#define ms(a, x) memset((a), (x), sizeof(a))
typedef vector <int> vi;
typedef vector <vi> vvi;
typedef vector <vvi> vvvi;
typedef vector <vvvi> vvvvi;
typedef vector <bool> vb;
typedef vector <vb> vvb;
typedef vector <vvb> vvvb;
typedef vector <vvvb> vvvvb;
typedef long long ll;
typedef vector <ll> vl;
typedef vector <vl> vvl;
typedef vector <vvl> vvvl;
typedef vector <vvvl> vvvvl;
typedef pair <int, int> ii;
typedef vector <ii> vii;
typedef vector <vii> vvii;
typedef pair <int, ll> il;
typedef vector <il> vil;
typedef vector <vil> vvil;
typedef pair <ll, int> li;
typedef vector <li> vli;
typedef vector <vli> vvli;
typedef set <int> si;
typedef set <li> sli;
typedef set <il> sil;
typedef vector <string> vs;
typedef vector <vs> vvs;
typedef vector <vvs> vvvs;
typedef map <char, int> mci;
typedef pair <ll, ll> pll;
typedef vector <pll> vll;
typedef long double ld;

const ld eps = 1e-22;

struct point {
    ld x, y;

    point() {}
    point(ld x, ld y) : x(x), y(y) {}
};

ld operator &(point a, point b) {
    return a.x * b.y - a.y * b.x;
}

point operator +(point a, point b) {
    return point(a.x - b.x, a.y - b.y);
}

point operator -(point a, point b) {
    return point(a.x - b.x, a.y - b.y);
}

ld len(point a) {
    return a.x * a.x + a.y * a.y;
}

bool operator ==(point a, point b) {
    return fabs(a.x - b.x) < eps && fabs(a.y - b.y) < eps;
}

void eprint(vector <pair <point, int> > a) {
    for (auto x: a) {
        cerr << x.second << ' ';
    }
    cerr << endl;
}

int main() {
    freopen("input.txt", "r", stdin);
    freopen("output.txt", "w", stdout);
    int n;
    cin >> n;
    if (n == 1) {
        cout << 1 << endl;
        return 0;
    }
    vector <pair <point, int> > a(n);
    for (int i = 0; i < n; ++i) {
        int s, r;
        cin >> s >> r;
        a[i] = mp(point(1.0 / s, 1.0 / r), i + 1);
    }
    int best = 0;
    for (int i = 1; i < n; ++i) {
        if (a[i].first.x < a[best].first.x || fabs(a[i].first.x - a[best].first.x) < eps && a[i].first.y < a[best].first.y) {
            best = i;
        }
    }
    cerr << best + 1 << endl;
    swap(a[0], a[best]);
    for (int i = 1; i < n; ++i) {
        a[i].first.x -= a[0].first.x;
        a[i].first.y -= a[0].first.y;
    }
    a[0].first = point(0.0, 0.0);
    sort(a.begin() + 1, a.end(), [](pair <point, int> A, pair <point, int> B) {
        auto a = A.first, b = B.first;
        ld mul = a & b;
        if (fabs(mul) < eps) {
            return len(a) < len(b);
        }
        return mul > 0;
    });
    eprint(a);
    vector <pair <point, int> > c;
    c.pb(a[0]);
    for (int i = 1; i < n; ++i) {
        while (sz(c) > 1 && ((a[i].first - c.back().first) & (c.back().first - c[sz(c) - 2].first)) > eps) {
            c.pop_back();
        }
        c.push_back(a[i]);
    }
    eprint(c);
    best = 0;
    for (int i = 0; i < sz(c); ++i) {
        if (c[i].first.y < c[best].first.y || fabs(c[i].first.y - c[best].first.y) < eps && c[i].first.x < c[best].first.x || c[i].first == c[best].first) {
            best = i;
        }
    }
    vi result;
    for (int i = 0; i <= best; ++i) {
        result.pb(c[i].second);
    }
    Sort(result);
    for (int x: result) {
        cout << x << ' ';
    }
    cout << endl;
}


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

typedef complex<double> cn;

const int N=2e5+10;
const double eps=1e-10;

vector<pair<cn, int> > hull, t;
int n;
vector<int> sol;

int dcmp (double x)
{
    return (x<-eps)?-1:(x>eps);
}

long double cross (cn a, cn b, cn c)
{
    return imag(conj(b-a)*(c-a));
}

bool cmp (const pair<cn, int> &a, const pair<cn, int> &b)
{
    if (dcmp(real(a.first)-real(b.first))==0) return imag(a.first)<imag(b.first);
    return real(a.first)<real(b.first);
}

void convexHull ()
{
    sort (t.begin(), t.end(), cmp);

    for (int i=0;i<2;i++)
    {
        int initSize=(int)hull.size();
        for (auto xt: t)
        {
            while (hull.size()>=initSize+2 && dcmp(cross(hull[hull.size()-2].first, hull.back().first, xt.first))<0) hull.pop_back();
            hull.push_back(xt);
        }

        hull.pop_back();
        reverse(t.begin(), t.end());
    }
}

int main()
{
    scanf ("%d", &n);
    for (int i=1;i<=n;i++)
    {
        double x, y;
        scanf ("%lf%lf", &x, &y);
        t.push_back({cn(10000.0/x, 10000.0/y), i});
    }

    convexHull();
    sol.push_back(hull[0].second);
    for (int i=1;i<hull.size();i++)
    {
        if (dcmp(imag(hull[i].first)-imag(hull[i-1].first))<=0) sol.push_back(hull[i].second);
        else break;
    }

    sort (sol.begin(), sol.end());
    for (auto idx: sol) printf ("%d ", idx);

    return 0;
}


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

typedef complex<double> cn;

const int N=2e5+10;
const double eps=1e-10;

vector<pair<cn, int> > hull, t;
int n;
vector<int> sol;
bool yes[N];

int dcmp (double x)
{
    return (x<-eps)?-1:(x>eps);
}

long double cross (cn a, cn b, cn c)
{
    return imag(conj(b-a)*(c-a));
}

bool cmp (const pair<cn, int> &a, const pair<cn, int> &b)
{
    if (dcmp(real(a.first)-real(b.first))==0)
    {
        if (dcmp(imag(a.first)-imag(b.first))==0) return a.second<b.second;
        return imag(a.first)<imag(b.first);
    }
    return real(a.first)<real(b.first);
}

void convexHull ()
{
    sort (t.begin(), t.end(), cmp);

    for (int i=0;i<2;i++)
    {
        int initSize=(int)hull.size();
        for (auto xt: t)
        {
            while (hull.size()>=initSize+2 && dcmp(cross(hull[hull.size()-2].first, hull.back().first, xt.first))<0) hull.pop_back();
            hull.push_back(xt);
        }

        hull.pop_back();
        reverse(t.begin(), t.end());
    }
}

int main()
{
    scanf ("%d", &n);
    for (int i=1;i<=n;i++)
    {
        double x, y;
        scanf ("%lf%lf", &x, &y);
        t.push_back({cn(10000.0/x, 10000.0/y), i});
    }

    convexHull();
    yes[hull[0].second]=true;
    for (int i=1;i<hull.size();i++)
    {
        if (dcmp(imag(hull[i].first)-imag(hull[i-1].first))<=0) yes[hull[i].second]=true;
        else break;
    }
    sort (t.begin(), t.end(), cmp);
    for (int i=1;i<t.size();i++)
    {
        if (dcmp(real(t[i].first)-real(t[i-1].first))==0 && dcmp(real(t[i].first)-imag(t[i-1].first))==0) yes[t[i].second]|=yes[t[i-1].second];
    }
    for (int i=1;i<=n;i++) if (yes[i]) printf ("%d ", i);
    for (auto idx: sol) printf ("%d ", idx);

    return 0;
}


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

typedef long double ld;

const int N=2e5+10;
const ld eps=1e-18;

struct pt
{
    ld x, y;
    vector<int> id;
    pt(): x(0.0), y(0.0) {}
    pt(ld X, ld Y): x(X), y(Y) {}
    bool operator<(const pt &other) const
    {
        return (x+eps<other.x || (fabs(x-other.x)<eps && y+eps<other.y));
    }
};

int n;
vector<pt> points;
map<pair<int, int>, int> idx;
bool valid[N];

ld cross (pt a, pt b, pt c)
{
    return ((a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y));
}

int main()
{
    scanf ("%d", &n);
    for (int i=0;i<n;i++)
    {
        int r, s;
        scanf ("%d%d", &r, &s);
        int id=points.size();
        if (idx.count(make_pair(r, s))) id=idx[make_pair(r, s)];
        if (id==points.size())
        {
            points.push_back(pt((ld)1.0/r, (ld)1.0/s));
            idx[make_pair(r, s)]=id;
        }
        points[id].id.push_back(i);
    }

    sort (points.begin(), points.end());
    vector<pt> down;

    for (auto xt: points)
    {
        while (down.size()>1 && cross(down[down.size()-2], xt, down.back())>eps) down.pop_back();
        down.push_back(xt);
    }

    for (int i=0;i<down.size();i++)
    {
        if (i && down[i].y+eps>down[i-1].y) break;
        for (int xt: down[i].id) valid[xt]=1;
    }

    for (int i=0;i<n;i++) if (valid[i]) printf ("%d ", i+1);

    return 0;
}


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

typedef long double ld;

const int N=2e5+10;
const ld eps=1e-10;

struct pt
{
    ld x, y;
    vector<int> id;
    pt(): x(0.0), y(0.0) {}
    pt(ld X, ld Y): x(X), y(Y) {}
    bool operator<(const pt &other) const
    {
        return (x+eps<other.x || (fabs(x-other.x)<eps && y+eps<other.y));
    }
};

int n;
vector<pt> points;
map<pair<int, int>, int> idx;
bool valid[N];

ld cross (pt a, pt b, pt c)
{
    return ((a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y));
}

int main()
{
    scanf ("%d", &n);
    for (int i=0;i<n;i++)
    {
        int r, s;
        scanf ("%d%d", &r, &s);
        int id=points.size();
        if (idx.count(make_pair(r, s))) id=idx[make_pair(r, s)];
        if (id==points.size())
        {
            points.push_back(pt((ld)1.0/r, (ld)1.0/s));
            idx[make_pair(r, s)]=id;
        }
        points[id].id.push_back(i);
    }

    sort (points.begin(), points.end());
    vector<pt> down;

    for (auto xt: points)
    {
        while (down.size()>1 && cross(down[down.size()-2], xt, down.back())>eps) down.pop_back();
        down.push_back(xt);
    }

    for (int i=0;i<down.size();i++)
    {
        if (i && down[i].y+eps>down[i-1].y) break;
        for (int xt: down[i].id) valid[xt]=1;
    }

    for (int i=0;i<n;i++) if (valid[i]) printf ("%d ", i+1);

    return 0;
}


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

typedef long double ld;

const int N=2e5+10;
const ld eps=1e-15;

struct pt
{
    ld x, y;
    vector<int> id;
    pt(): x(0.0), y(0.0) {}
    pt(ld X, ld Y): x(X), y(Y) {}
    bool operator<(const pt &other) const
    {
        return (x+eps<other.x || (fabs(x-other.x)<eps && y+eps<other.y));
    }
};

int n;
vector<pt> points;
map<pair<int, int>, int> idx;
bool valid[N];

ld cross (pt a, pt b, pt c)
{
    return ((a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y));
}

int main()
{
    scanf ("%d", &n);
    for (int i=0;i<n;i++)
    {
        int r, s;
        scanf ("%d%d", &r, &s);
        int id=points.size();
        if (idx.count(make_pair(r, s))) id=idx[make_pair(r, s)];
        if (id==points.size())
        {
            points.push_back(pt((ld)1.0/r, (ld)1.0/s));
            idx[make_pair(r, s)]=id;
        }
        points[id].id.push_back(i);
    }

    sort (points.begin(), points.end());
    vector<pt> down;

    for (auto xt: points)
    {
        while (down.size()>1 && cross(down[down.size()-2], xt, down.back())>eps) down.pop_back();
        down.push_back(xt);
    }

    for (int i=0;i<down.size();i++)
    {
        if (i && down[i].y+eps>down[i-1].y) break;
        for (int xt: down[i].id) valid[xt]=1;
    }

    for (int i=0;i<n;i++) if (valid[i]) printf ("%d ", i+1);

    return 0;
}


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

typedef complex<double> cn;

const int N=2e5+10;
const double eps=1e-22;

vector<pair<cn, int> > hull, t;
int n;
vector<int> sol;

long double cross (cn a, cn b, cn c)
{
    return imag(conj(b-a)*(c-a));
}

bool cmp (const pair<cn, int> &a, const pair<cn, int> &b)
{
    if (real(a.first)==real(b.first)) return imag(a.first)<=imag(b.first);
    return real(a.first)<real(b.first);
}

void convexHull ()
{
    sort (t.begin(), t.end(), cmp);

    for (int i=0;i<2;i++)
    {
        int initSize=(int)hull.size();
        for (auto xt: t)
        {
            while (hull.size()>=initSize+2 && cross(hull[hull.size()-2].first, hull.back().first, xt.first)<-eps) hull.pop_back();
            hull.push_back(xt);
        }

        hull.pop_back();
        reverse(t.begin(), t.end());
    }
}

int main()
{
    scanf ("%d", &n);
    for (int i=1;i<=n;i++)
    {
        double x, y;
        scanf ("%lf%lf", &x, &y);
        t.push_back({cn(1.0/x, 1.0/y), i});
    }

    convexHull();
    sol.push_back(hull[0].second);
    for (int i=1;i<hull.size();i++)
    {
        if (imag(hull[i].first)<=imag(hull[i-1].first)+eps) sol.push_back(hull[i].second);
        else break;
    }

    sort (sol.begin(), sol.end());
    for (auto idx: sol) printf ("%d ", idx);

    return 0;
}


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

typedef complex<double> cn;

const int N=2e5+10;
const double eps=1e-10;

vector<pair<cn, int> > hull, t;
int n;
vector<int> sol;

int dcmp (double x)
{
    return (x<-eps)?-1:(x>eps);
}

long double cross (cn a, cn b, cn c)
{
    return imag(conj(b-a)*(c-a));
}

bool cmp (const pair<cn, int> &a, const pair<cn, int> &b)
{
    if (dcmp(real(a.first)-real(b.first))==0) return imag(a.first)<imag(b.first);
    return real(a.first)<real(b.first);
}

void convexHull ()
{
    sort (t.begin(), t.end(), cmp);

    for (int i=0;i<2;i++)
    {
        int initSize=(int)hull.size();
        for (auto xt: t)
        {
            while (hull.size()>=initSize+2 && dcmp(cross(hull[hull.size()-2].first, hull.back().first, xt.first))<0) hull.pop_back();
            hull.push_back(xt);
        }

        hull.pop_back();
        reverse(t.begin(), t.end());
    }
}

int main()
{
    scanf ("%d", &n);
    for (int i=1;i<=n;i++)
    {
        double x, y;
        scanf ("%lf%lf", &x, &y);
        t.push_back({cn(10000.0/x, 10000.0/y), i});
    }

    convexHull();
    sol.push_back(hull[0].second);
    for (int i=1;i<hull.size();i++)
    {
        if (dcmp(imag(hull[i].first)-imag(hull[i-1].first))<=0) sol.push_back(hull[i].second);
        else break;
    }
    for (int i=hull.size()-1;i>=1;i--)
    {
        if (dcmp(real(hull[i].first)-real(hull[0].first))==0) sol.push_back(hull[i].second);
    }

    sort (sol.begin(), sol.end());
    for (auto idx: sol) printf ("%d ", idx);

    return 0;
}


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

typedef long double ld;

const int N=2e5+10;
const ld eps=1e-20;

struct pt
{
    ld x, y;
    vector<int> id;
    pt(): x(0.0), y(0.0) {}
    pt(ld X, ld Y): x(X), y(Y) {}
    bool operator<(const pt &other) const
    {
        return (x+eps<other.x || (fabs(x-other.x)<eps && y+eps<other.y));
    }
};

int n;
vector<pt> points;
map<pair<int, int>, int> idx;
bool valid[N];

ld cross (pt a, pt b, pt c)
{
    return ((a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y));
}

int main()
{
    scanf ("%d", &n);
    for (int i=0;i<n;i++)
    {
        int r, s;
        scanf ("%d%d", &r, &s);
        int id=points.size();
        if (idx.count(make_pair(r, s))) id=idx[make_pair(r, s)];
        if (id==points.size())
        {
            points.push_back(pt((ld)1.0/r, (ld)1.0/s));
            idx[make_pair(r, s)]=id;
        }
        points[id].id.push_back(i);
    }

    sort (points.begin(), points.end());
    vector<pt> down;

    for (auto xt: points)
    {
        while (down.size()>1 && cross(down[down.size()-2], xt, down.back())>eps) down.pop_back();
        down.push_back(xt);
    }

    for (int i=0;i<down.size();i++)
    {
        if (i && down[i].y+eps>down[i-1].y) break;
        for (int xt: down[i].id) valid[xt]=1;
    }

    for (int i=0;i<n;i++) if (valid[i]) printf ("%d ", i+1);

    return 0;
}


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

typedef long double ld;

const int N=2e5+10;
const ld eps=1e-18;

struct pt
{
    ld x, y;
    vector<int> id;
    pt(): x(0.0), y(0.0) {}
    pt(ld X, ld Y): x(X), y(Y) {}
    bool operator<(const pt &other) const
    {
        return x+eps<other.x || fabs(x-other.x)<eps && y+eps<other.y;
    }
};

int n;
vector<pt> points;
map<pair<int, int>, int> idx;
bool valid[N];

ld cross (pt a, pt b, pt c)
{
    return ((a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y));
}

int main()
{
    scanf ("%d", &n);
    for (int i=0;i<n;i++)
    {
        int r, s;
        scanf ("%d%d", &r, &s);
        int id=points.size();
        if (idx.count(make_pair(r, s))) id=idx[make_pair(r, s)];
        if (id==points.size())
        {
            points.push_back(pt((ld)1.0/r, (ld)1.0/s));
            idx[make_pair(r, s)]=id;
        }
        points[id].id.push_back(i);
    }

    sort (points.begin(), points.end());
    vector<pt> down;

    for (auto xt: points)
    {
        while (down.size()>1 && cross(down[down.size()-2], xt, down.back())>eps) down.pop_back();
        down.push_back(xt);
    }

    for (int i=0;i<down.size();i++)
    {
        if (i && down[i].y+eps>down[i-1].y) break;
        for (int xt: down[i].id) valid[xt]=1;
    }

    for (int i=0;i<n;i++) if (valid[i]) printf ("%d ", i+1);

    return 0;
}


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

typedef complex<double> cn;

const int N=2e5+10;
const double eps=1e-20;

vector<pair<cn, int> > hull, t;
int n;
vector<int> sol;

long double cross (cn a, cn b, cn c)
{
    return imag(conj(b-a)*(c-a));
}

bool cmp (const pair<cn, int> &a, const pair<cn, int> &b)
{
    if (real(a.first)==real(b.first)) return imag(a.first)<=imag(b.first);
    return real(a.first)<real(b.first);
}

int dcmp (double x)
{
    return (x<-eps)?-1:(x>eps);
}

void convexHull ()
{
    sort (t.begin(), t.end(), cmp);

    for (int i=0;i<2;i++)
    {
        int initSize=(int)hull.size();
        for (auto xt: t)
        {
            while (hull.size()>=initSize+2 && dcmp(cross(hull[hull.size()-2].first, hull.back().first, xt.first))<0) hull.pop_back();
            hull.push_back(xt);
        }

        hull.pop_back();
        reverse(t.begin(), t.end());
    }
}

int main()
{
    scanf ("%d", &n);
    for (int i=1;i<=n;i++)
    {
        double x, y;
        scanf ("%lf%lf", &x, &y);
        t.push_back({cn(1.0/x, 1.0/y), i});
    }

    convexHull();
    sol.push_back(hull[0].second);
    for (int i=1;i<hull.size();i++)
    {
        if (dcmp(imag(hull[i].first)-imag(hull[i-1].first))<=0) sol.push_back(hull[i].second);
        else break;
    }

    sort (sol.begin(), sol.end());
    for (auto idx: sol) printf ("%d ", idx);

    return 0;
}


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

typedef complex<double> cn;

const int N=2e5+10;
const double eps=1e-22;

vector<pair<cn, int> > hull, t;
int n;
vector<int> sol;

long double cross (cn a, cn b, cn c)
{
    return imag(conj(b-a)*(c-a));
}

bool cmp (const pair<cn, int> &a, const pair<cn, int> &b)
{
    if (real(a.first)==real(b.first)) return imag(a.first)<=imag(b.first);
    return real(a.first)<real(b.first);
}

void convexHull ()
{
    sort (t.begin(), t.end(), cmp);

    for (int i=0;i<2;i++)
    {
        int initSize=(int)hull.size();
        for (auto xt: t)
        {
            while (hull.size()>=initSize+2 && cross(hull[hull.size()-2].first, hull.back().first, xt.first)<-eps) hull.pop_back();
            hull.push_back(xt);
        }

        hull.pop_back();
        reverse(t.begin(), t.end());
    }
}

int main()
{
    scanf ("%d", &n);
    for (int i=1;i<=n;i++)
    {
        double x, y;
        scanf ("%lf%lf", &x, &y);
        t.push_back({cn(1.0/x, 1.0/y), i});
    }

    convexHull();
    sol.push_back(hull[0].second);
    for (int i=1;i<hull.size();i++)
    {
        if (imag(hull[i].first)<=imag(hull[i-1].first)-eps) sol.push_back(hull[i].second);
        else break;
    }

    sort (sol.begin(), sol.end());
    for (auto idx: sol) printf ("%d ", idx);

    return 0;
}


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

typedef complex<double> cn;

const int N=2e5+10;
const double eps=1e-20;

vector<pair<cn, int> > hull, t;
int n;
vector<int> sol;

long double cross (cn a, cn b, cn c)
{
    return imag(conj(b-a)*(c-a));
}

bool cmp (const pair<cn, int> &a, const pair<cn, int> &b)
{
    if (real(a.first)==real(b.first)) return imag(a.first)<=imag(b.first);
    return real(a.first)<real(b.first);
}

void convexHull ()
{
    sort (t.begin(), t.end(), cmp);

    for (int i=0;i<2;i++)
    {
        int initSize=(int)hull.size();
        for (auto xt: t)
        {
            while (hull.size()>=initSize+2 && cross(hull[hull.size()-2].first, hull.back().first, xt.first)<-eps) hull.pop_back();
            hull.push_back(xt);
        }

        hull.pop_back();
        reverse(t.begin(), t.end());
    }
}

int main()
{
    scanf ("%d", &n);
    for (int i=1;i<=n;i++)
    {
        double x, y;
        scanf ("%lf%lf", &x, &y);
        t.push_back({cn(1.0/x, 1.0/y), i});
    }

    convexHull();
    sol.push_back(hull[0].second);
    for (int i=1;i<hull.size();i++)
    {
        if (imag(hull[i].first)<=imag(hull[i-1].first)+eps) sol.push_back(hull[i].second);
        else break;
    }

    sort (sol.begin(), sol.end());
    for (auto idx: sol) printf ("%d ", idx);

    return 0;
}


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

typedef long double ld;

const int N=2e5+10;
const ld eps=1e-17;

struct pt
{
    ld x, y;
    vector<int> id;
    pt(): x(0.0), y(0.0) {}
    pt(ld X, ld Y): x(X), y(Y) {}
    bool operator<(const pt &other) const
    {
        return (x+eps<other.x || (fabs(x-other.x)<eps && y+eps<other.y));
    }
};

int n;
vector<pt> points;
map<pair<int, int>, int> idx;
bool valid[N];

ld cross (pt a, pt b, pt c)
{
    return ((a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y));
}

int main()
{
    scanf ("%d", &n);
    for (int i=0;i<n;i++)
    {
        int r, s;
        scanf ("%d%d", &r, &s);
        int id=points.size();
        if (idx.count(make_pair(r, s))) id=idx[make_pair(r, s)];
        if (id==points.size())
        {
            points.push_back(pt((ld)1.0/r, (ld)1.0/s));
            idx[make_pair(r, s)]=id;
        }
        points[id].id.push_back(i);
    }

    sort (points.begin(), points.end());
    vector<pt> down;

    for (auto xt: points)
    {
        while (down.size()>1 && cross(down[down.size()-2], xt, down.back())>eps) down.pop_back();
        down.push_back(xt);
    }

    for (int i=0;i<down.size();i++)
    {
        if (i && down[i].y+eps>down[i-1].y) break;
        for (int xt: down[i].id) valid[xt]=1;
    }

    for (int i=0;i<n;i++) if (valid[i]) printf ("%d ", i+1);

    return 0;
}


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

typedef long double ld;

const int N=2e5+10;
const ld eps=1e-12;

struct pt
{
    ld x, y;
    vector<int> id;
    pt(): x(0.0), y(0.0) {}
    pt(ld X, ld Y): x(X), y(Y) {}
    bool operator<(const pt &other) const
    {
        return (x+eps<other.x || (fabs(x-other.x)<eps && y+eps<other.y));
    }
};

int n;
vector<pt> points;
map<pair<int, int>, int> idx;
bool valid[N];

ld cross (pt a, pt b, pt c)
{
    return ((a.x-c.x)*(b.y-c.y)-(b.x-c.x)*(a.y-c.y));
}

int main()
{
    scanf ("%d", &n);
    for (int i=0;i<n;i++)
    {
        int r, s;
        scanf ("%d%d", &r, &s);
        int id=points.size();
        if (idx.count(make_pair(r, s))) id=idx[make_pair(r, s)];
        if (id==points.size())
        {
            points.push_back(pt((ld)1.0/r, (ld)1.0/s));
            idx[make_pair(r, s)]=id;
        }
        points[id].id.push_back(i);
    }

    sort (points.begin(), points.end());
    vector<pt> down;

    for (auto xt: points)
    {
        while (down.size()>1 && cross(down[down.size()-2], xt, down.back())>eps) down.pop_back();
        down.push_back(xt);
    }

    for (int i=0;i<down.size();i++)
    {
        if (i && down[i].y+eps>down[i-1].y) break;
        for (int xt: down[i].id) valid[xt]=1;
    }

    for (int i=0;i<n;i++) if (valid[i]) printf ("%d ", i+1);

    return 0;
}


#include <iostream>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <cstring>
#include <queue>
#include <ctime>
#include <cassert>
#include <cstdio>
#include <algorithm>
#include <unordered_set>
#include <unordered_map>

using namespace std;

#define fr first
#define sc second
#define mp make_pair
#define pb push_back
#define epr(...) fprintf(stderr, __VA_ARGS__)

#define equal equalll
#define less lesss
const int N = 2e5 + 10;
const int INF = 1e9;

struct fraq {
    long long x, y;
    fraq() { }
    fraq(long long x) {
        y = 1;
        this->x = x;
    }
    fraq(long long x, long long y): x(x), y(y) {
        assert(y != 0);
        if (y < 0) {
            this->x *= -1;
            this->y *= -1;
        }
    }
    bool operator < (fraq other) {
        return x * other.y < other.x * y;
    }
    bool operator > (fraq other) {
        return x * other.y > other.x * y;
    }

    bool operator == (fraq other) {
        return x * other.y == other.x * y;
    }
    fraq operator * (fraq A) {
        return fraq(x * A.x, y * A.y);
    }
    fraq operator + (fraq A) {
        return fraq(x * A.y + A.x * y, y * A.y);
    }
    fraq operator - (fraq A) {
        return fraq(x * A.y - A.x * y, y * A.y);
    }
    void Epr() {
        epr("(%lld / %lld)\n", x, y);
        //epr("%lf\\c , x, y);
    }
};

struct pnt {
    fraq x, y;
    int id;
    pnt () { }
    pnt (fraq x, fraq y): x(x), y(y) { }
    pnt operator - (pnt A) {
        return pnt(x - A.x, y - A.y);
    }
    fraq operator * (pnt A) {
        return x * A.y - y * A.x;
    }
    fraq len2() {
        return x * x + y * y;
    }
    void Epr() {
        //cerr << "pnt x y:\n";
        epr("(%.3lf, %.3lf)\n", x.x * 1.0 / x.y, y.x * 1.0 / y.y);
        //x.Epr();
        //y.Epr();
    }
};

int n;
pnt p[N];
map < pair < int, int >, vector < int > > q;
pnt O;

void read() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        q[mp(x, y)].pb(i);
        p[i] = pnt(fraq(1, x), fraq(1, y));
    }
}

bool cmpO(pnt A, pnt B) {
    A = A - O;
    B = B - O;
    return A * B > fraq(0, 1) || (A * B == fraq(0, 1) && A.len2() < B.len2());
}

void convexHull() {
    for (int i = 0; i < n; i++)
        if (p[i].x < p[0].x || (p[0].x == p[i].x && p[i].y < p[0].y))
            swap(p[i], p[0]);
    O = p[0];
    sort(p + 1, p + n, cmpO);
    //for (int i = 0; i < n; i++)
        //p[i].Epr();
    int cur = 0;
    for (int i = 0; i < n; i++) {
        for (; cur >= 2 && (p[cur - 1] - p[cur - 2]) * (p[i] - p[cur - 1]) < 0; cur--);
        p[cur++] = p[i];
    }
    n = cur;
    for (int i = 1; i < n; i++) {
        if (p[i].y > p[i - 1].y) {
            n = i;
            break;
        }
    }
}

void solve() {
    convexHull();
    vector < int > res;
    for (int i = 0; i < n; i++) {
        auto pr = mp(p[i].x.y, p[i].y.y);
        vector < int > g = q[pr];
        for (auto x: g)
            res.pb(x);
    }
    sort(res.begin(), res.end());
    for (auto x: res)
        printf("%d ", x + 1);
    printf("\n");
}

void printAns() {

}

void stress() {

}

int main(){
#ifdef DEBUG
    freopen("in", "r", stdin);
    //freopen("out", "w", stdout);
#endif
    if (1) {
        int k = 1;
        for (int tt = 0; tt < k; tt++) {
            read();
            solve();
            printAns();
        }
    }
    else {
        stress();
    }

    return 0;
}


#include <iostream>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <cstring>
#include <queue>
#include <ctime>
#include <cassert>
#include <cstdio>
#include <algorithm>
#include <unordered_set>
#include <unordered_map>

using namespace std;

#define fr first
#define sc second
#define mp make_pair
#define pb push_back
#define epr(...) fprintf(stderr, __VA_ARGS__)

#define equal equalll
#define less lesss
const int N = 2e5 + 10;
const int INF = 1e9;

struct person {
    int r, c, id;
    bool operator == (person a) {
        return a.r == r && a.c == a.c;
    }
    void Epr() {
        cerr << "r c id: " << r << " " << c << " " << id << endl;
    }
};

struct fraq {
    long long x, y;
    fraq() { }
    fraq(long long x, long long y) {
        //assert(y != 0);
        if (y < 0) {
            x *= -1;
            y *= -1;
        }
        this->x = x;
        this->y = y;
    }

    bool operator < (fraq other) const {
        return x * other.y < y * other.x;
    }
    bool operator == (fraq other) const {
        return x * other.y == y * other.x;
    }
    void Epr() {
        cerr << x << "/" << y << endl;
    }
};

int n;
person b[N];
person val[N];
int cur;
vector < int > who[N];
set < pair < fraq, int > > q;

void read() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%d%d", &b[i].r, &b[i].c);
        b[i].id = i;
    }
}

bool cmpC(person a, person b) {
    return a.c < b.c;
}

fraq when (person a, person b) {
    //assert(a.c < b.c);
    long long X = a.r * 1ll * b.r * (a.c - b.c);
    long long Y = (a.c - a.r) * 1ll * b.r * b.c +
            a.r * 1ll * a.c * (b.r - b.c);
    return fraq(Y - X, Y);
}

void solve() {
    sort(b, b + n, cmpC);
    //for (int i = 0; i < n; i++)
        //b[i].Epr();
    cur = 0;

    for (int i = 0; i < n; i++) {
        for (; cur > 0 && (val[cur - 1].r < b[i].r ||
                    (val[cur - 1].r == b[i].r && val[cur - 1].c < b[i].c)); cur--);
        if (cur > 0 && b[i].c == val[cur - 1].c && b[i].r < val[cur - 1].r) continue;
        if (val[cur - 1] == b[i]) {
            who[cur - 1].pb(b[i].id);
        }
        else {
            who[cur].clear();
            cur++;
            who[cur - 1].pb(b[i].id);
            val[cur - 1] = b[i];
        }
    }
    for (int i = 0; i < cur; i++)
        val[i].id = i;

    //cerr << "cur: " << cur << endl;

    vector < int > answer;
    //q.insert(mp(fraq(0, 1), 0));
    for (int i = 1; i < cur; i++) {
        fraq d = when(val[0], val[i]);
        q.insert(mp(d, i));
    }

    answer.pb(0);
    int cur = 0;
    //cerr << q.size() << endl;
    while (!q.empty()) {
        //cerr << "new iter\n";
        pair < fraq, int > tmp;
        bool flag = 1;
        for (;;) {
            if (q.empty()) {
                flag = 0;
                break;
            }
            tmp = *(q.begin());
            q.erase(q.begin());
            //cerr << "cur: " << cur << " " << tmp.sc << endl;
            if (tmp.sc < cur) continue;
            fraq tmr = when(val[cur], val[tmp.sc]);
            //cerr << "tmr\n";
            //tmr.Epr();
            if (tmr == tmp.fr)
                break;
            //assert(tmp.fr < tmr);
            tmp.fr = tmr;
            q.insert(tmp);
        }
        //cerr << "q.size(): " << q.size() << endl;;
        if (flag == 0) break;
        cur = tmp.sc;
        answer.pb(cur);
    }
    //cerr << "answer sz: " << answer.size() << endl;
    vector < int > res;
    for (auto x: answer)
        for (auto y: who[x])
            res.pb(y);
    sort(res.begin(), res.end());
    for (auto y: res)
        printf("%d ", y + 1);
    printf("\n");
}

void printAns() {

}

void stress() {

}

int main(){
#ifdef DEBUG
    freopen("in", "r", stdin);
    //freopen("out", "w", stdout);
#endif
    if (1) {
        int k = 1;
        for (int tt = 0; tt < k; tt++) {
            read();
            solve();
            printAns();
        }
    }
    else {
        stress();
    }

    return 0;
}


#include <iostream>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <cstring>
#include <queue>
#include <ctime>
#include <cassert>
#include <cstdio>
#include <algorithm>
#include <unordered_set>
#include <unordered_map>

using namespace std;

#define fr first
#define sc second
#define mp make_pair
#define pb push_back
#define epr(...) fprintf(stderr, __VA_ARGS__)

#define equal equalll
#define less lesss
const int N = 2e5 + 10;
const int INF = 1e9;

struct person {
    int r, c, id;
    bool operator == (person a) {
        return a.r == r && a.c == a.c;
    }
    void Epr() {
        cerr << "r c id: " << r << " " << c << " " << id << endl;
    }
};

struct fraq {
    long long x, y;
    fraq() { }
    fraq(long long x, long long y) {
        assert(y != 0);
        if (y < 0) {
            x *= -1;
            y *= -1;
        }
        this->x = x;
        this->y = y;
    }

    bool operator < (fraq other) const {
        return x * other.y < y * other.x;
    }
    bool operator == (fraq other) const {
        return x * other.y == y * other.x;
    }
    void Epr() {
        cerr << x << "/" << y << endl;
    }
};

int n;
person b[N];
person val[N];
int cur;
vector < int > who[N];
set < pair < fraq, int > > q;

void read() {
    scanf("%d", &n);
    for (int i = 0; i < n; i++) {
        scanf("%d%d", &b[i].r, &b[i].c);
        b[i].id = i;
    }
}

bool cmpC(person a, person b) {
    return a.c < b.c;
}

fraq when (person a, person b) {
    assert(a.c < b.c);
    long long X = a.r * 1ll * b.r * (a.c - b.c);
    long long Y = (a.c - a.r) * 1ll * b.r * b.c +
            a.r * 1ll * a.c * (b.r - b.c);
    return fraq(Y - X, Y);
}

void solve() {
    sort(b, b + n, cmpC);
    //for (int i = 0; i < n; i++)
        //b[i].Epr();
    cur = 0;

    for (int i = 0; i < n; i++) {
        for (; cur > 0 && (val[cur - 1].r < b[i].r ||
                    (val[cur - 1].r == b[i].r && val[cur - 1].c < b[i].c)); cur--);
        if (cur > 0 && b[i].c == val[cur - 1].c && b[i].r < val[cur - 1].r) continue;
        if (val[cur - 1] == b[i]) {
            who[cur - 1].pb(b[i].id);
        }
        else {
            who[cur].clear();
            cur++;
            who[cur - 1].pb(b[i].id);
            val[cur - 1] = b[i];
        }
    }
    for (int i = 0; i < cur; i++)
        val[i].id = i;

    //cerr << "cur: " << cur << endl;

    vector < int > answer;
    //q.insert(mp(fraq(0, 1), 0));
    for (int i = 1; i < cur; i++) {
        fraq d = when(val[0], val[i]);
        //d.Epr();
        //val[i].Epr();
        q.insert(mp(d, i));
    }

    answer.pb(0);
    int cur = 0;
    //cerr << q.size() << endl;
    while (!q.empty()) {
        //cerr << "new iter\n";
        pair < fraq, int > tmp;
        bool flag = 1;
        for (;;) {
            if (q.empty()) {
                flag = 0;
                break;
            }
            tmp = *(q.begin());
            q.erase(q.begin());
            //cerr << "cur: " << cur << " " << tmp.sc << endl;
            if (tmp.sc < cur) continue;
            fraq tmr = when(val[cur], val[tmp.sc]);
            //cerr << "tmr\n";
            //tmr.Epr();
            if (tmr == tmp.fr)
                break;
            assert(tmp.fr < tmr);
            tmp.fr = tmr;
            q.insert(tmp);
        }
        //cerr << "q.size(): " << q.size() << endl;;
        if (flag == 0) break;
        cur = tmp.sc;
        answer.pb(cur);
    }
    //cerr << "answer sz: " << answer.size() << endl;
    vector < int > res;
    for (auto x: answer)
        for (auto y: who[x])
            res.pb(y);
    sort(res.begin(), res.end());
    for (auto y: res)
        printf("%d ", y + 1);
    printf("\n");
}

void printAns() {

}

void stress() {

}

int main(){
#ifdef DEBUG
    freopen("in", "r", stdin);
    //freopen("out", "w", stdout);
#endif
    if (1) {
        int k = 1;
        for (int tt = 0; tt < k; tt++) {
            read();
            solve();
            printAns();
        }
    }
    else {
        stress();
    }

    return 0;
}


#include <iostream>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <cstring>
#include <queue>
#include <ctime>
#include <cassert>
#include <cstdio>
#include <algorithm>
#include <unordered_set>
#include <unordered_map>

using namespace std;

#define fr first
#define sc second
#define mp make_pair
#define pb push_back
#define epr(...) fprintf(stderr, __VA_ARGS__)

#define equal equalll
#define less lesss
const int N = 2e5 + 10;
const long long INF = 1e17;

bool equal(double a, double b) {
    return abs(a - b) < 1e-9;
}

bool less(double a, double b) {
    return a < b && !equal(a, b);
}

bool lessE(double a, double b) {
    return a < b || equal(a, b);
}

struct pnt {
    double x, y;
    int id;
    pnt () { }
    pnt (double x, double y): x(x), y(y) { }
    pnt operator - (pnt A) {
        return pnt(x - A.x, y - A.y);
    }
    pnt operator + (pnt A) {
        return pnt(x + A.x, y + A.y);
    }
    double operator * (pnt A) {
        return x * A.y - y * A.x;
    }
    bool operator == (pnt A) {
        return x == A.x && y == A.y;
    }
    double len2() {
        return x * x + y * y;
    }
    void Epr() {
        //epr("(
        //cerr << "pnt x y:\n";
        //int T = 1e4;
        //epr("(%.7lf, %.7lf)\n", x.x * 1.0 / x.y * T , y.x * 1.0 / y.y * T);
        //x.Epr();
        //y.Epr();
    }
};

int n;
pnt p[N];
map < pair < int, int >, vector < int > > q;
pnt O;

void read() {
    scanf("%d", &n);
    int cur = 0;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        q[mp(x, y)].pb(i);
        if ((int)q[mp(x, y)].size() == 1)
            p[cur++] = pnt(1.0 / x, 1.0 / y);
    }
    n = cur;
}

bool cmpO(pnt A, pnt B) {
    //pnt OldA = A;
    A = A - O;
    B = B - O;
    //pnt D = A + O;
    //A.x.Epr();
    //A.y.Epr();
    //cerr << "-------------\n";
    //D.x.Epr();
    //D.y.Epr();

    //assert(OldA == D);
    //int r = 0;
    //r += A * B > 0;
    //r += A * B < 0;
    //r += A * B == 0;
    //assert(r == 1);
    //return A * B > 0 || (A * B == 0 && A.len2() < B.len2());
    //check(A, 8);
    return A * B > 0 || (A * B == 0 && (A.x < B.x || (A.x == B.x && A.y < B.y)));
}

void convexHull() {
    for (int i = 0; i < n; i++)
        if (p[i].x < p[0].x || (p[0].x == p[i].x && less(p[i].y, p[0].y)))
            swap(p[i], p[0]);
    //cerr << "first\n";

    //int M = 10;
    O = p[0];
    //cerr << "O: ";
    //O.Epr();
    sort(p + 1, p + n, cmpO);
    //cerr << "second\n";
    //for (int i = 1; i < n - 1; i++)
        //assert(cmpO(p[i], p[i + 1]) == 1);
    //vector < pnt > h;

    //for (int i = 0; i < M; i++) {
        //p[i].Epr();
    //}
    //for (int i = 0; i < n; i++)
        //h.pb(p[i]);
    //cerr << "-------\n";

    //sort(p + 1, p + n, cmpO);
    //for (int i = 1; i < n - 1; i++) {
        //assert(cmpO(p[i], p[i + 1]) == 1);
        //assert(cmpO(p[i + 1], p[i]) == 0);
    //}

    //for (int i = 0; i < M; i++) {
        //p[i].Epr();
    //}
    //for (int i = 0; i < n; i++) {
        ////cerr << "comp Pair\n";
        ////p[i].Epr();
        ////h[i].Epr();
        //assert(p[i] == h[i]);
    //}
    //cerr << "convex\n";

    int cur = 0;
    for (int i = 0; i < n; i++) {
        //for (; cur >= 2 && (p[cur - 1] - p[cur - 2]) * (p[i] - p[cur - 1]) < 0; cur--);

        for (;;) {
            if (cur < 2) break;
            pnt r1 = (p[cur - 1] - p[cur - 2]);
            //check(r1, 8);
            pnt r2 = (p[i] - p[cur - 1]);
            //check(r2, 8);
            double r3 = r1 * r2;
            //check(pnt(double(0), r3), 16);
            if (less(r3, 0)) {
                cur--;
            }
            else
                break;
        }
        p[cur++] = p[i];
    }
    //cerr << "third\n";
    //cerr << "n: " << n << endl;
    n = cur;
    //cerr << "n: " << n << endl;
    //for (int i = 0; i < 20; i++)
        //p[i].Epr();
    for (int i = 1; i < n; i++) {
        if (!(less(p[i].y, p[i - 1].y))) {
            n = i;
            break;
        }
    }
    //cerr << "n: " << n << endl;
}

void solve() {
    convexHull();
    vector < int > res;
    for (int i = 0; i < n; i++) {
        auto pr = mp((int)round(1 / p[i].x), (int)round(1 / p[i].y));
        vector < int > g = q[pr];
        for (auto x: g)
            res.pb(x);
    }
    sort(res.begin(), res.end());
    for (auto x: res)
        printf("%d ", x + 1);
    printf("\n");
}

void printAns() {

}

void stress() {

}

int main(){
#ifdef DEBUG
    freopen("in", "r", stdin);
    freopen("test.txt", "r", stdin);
    //freopen("out", "w", stdout);
#endif
    if (1) {
        int k = 1;
        for (int tt = 0; tt < k; tt++) {
            read();
            solve();
            printAns();
        }
    }
    else {
        stress();
    }

    return 0;
}


#include <iostream>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <cstring>
#include <queue>
#include <ctime>
#include <cassert>
#include <cstdio>
#include <algorithm>
#include <unordered_set>
#include <unordered_map>

using namespace std;

#define fr first
#define sc second
#define mp make_pair
#define pb push_back
#define epr(...) fprintf(stderr, __VA_ARGS__)

#define equal equalll
#define less lesss
const int N = 2e5 + 10;
const int INF = 1e9;

struct fraq {
    long long x, y;
    fraq() { }
    fraq(long long x) {
        y = 1;
        this->x = x;
    }
    fraq(long long x, long long y): x(x), y(y) {
        assert(y != 0);
        if (y < 0) {
            this->x *= -1;
            this->y *= -1;
        }
    }
    bool operator < (fraq other) {
        return x * other.y < other.x * y;
    }
    bool operator > (fraq other) {
        return x * other.y > other.x * y;
    }

    bool operator == (fraq other) {
        return x * other.y == other.x * y;
    }
    fraq operator * (fraq A) {
        return fraq(x * A.x, y * A.y);
    }
    fraq operator + (fraq A) {
        return fraq(x * A.y + A.x * y, y * A.y);
    }
    fraq operator - (fraq A) {
        return fraq(x * A.y - A.x * y, y * A.y);
    }
    void Epr() {
        epr("(%lld / %lld)\n", x, y);
        //epr("%lf\\c , x, y);
    }
};

struct pnt {
    fraq x, y;
    int id;
    pnt () { }
    pnt (fraq x, fraq y): x(x), y(y) { }
    pnt operator - (pnt A) {
        return pnt(x - A.x, y - A.y);
    }
    fraq operator * (pnt A) {
        return x * A.y - y * A.x;
    }
    fraq len2() {
        return x * x + y * y;
    }
    void Epr() {
        //cerr << "pnt x y:\n";
        epr("(%.3lf, %.3lf)\n", x.x * 1.0 / x.y, y.x * 1.0 / y.y);
        //x.Epr();
        //y.Epr();
    }
};

int n;
pnt p[N];
map < pair < int, int >, vector < int > > q;
pnt O;

void read() {
    scanf("%d", &n);
    int cur = 0;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        q[mp(x, y)].pb(i);
        if ((int)q[mp(x, y)].size() == 1)
            p[cur++] = pnt(fraq(1, x), fraq(1, y));
    }
    n = cur;
}

bool cmpO(pnt A, pnt B) {
    A = A - O;
    B = B - O;
    return A * B > fraq(0, 1) || (A * B == fraq(0, 1) && A.len2() < B.len2());
}

void convexHull() {
    for (int i = 0; i < n; i++)
        if (p[i].x < p[0].x || (p[0].x == p[i].x && p[i].y < p[0].y))
            swap(p[i], p[0]);
    O = p[0];
    sort(p + 1, p + n, cmpO);
    //for (int i = 0; i < n; i++)
        //p[i].Epr();
    int cur = 0;
    for (int i = 0; i < n; i++) {
        for (; cur >= 2 && (p[cur - 1] - p[cur - 2]) * (p[i] - p[cur - 1]) < 0; cur--);
        p[cur++] = p[i];
    }
    n = cur;
    for (int i = 1; i < n; i++) {
        if (p[i].y > p[i - 1].y) {
            n = i;
            break;
        }
    }
}

void solve() {
    convexHull();
    vector < int > res;
    for (int i = 0; i < n; i++) {
        auto pr = mp(p[i].x.y, p[i].y.y);
        vector < int > g = q[pr];
        for (auto x: g)
            res.pb(x);
    }
    sort(res.begin(), res.end());
    for (auto x: res)
        printf("%d ", x + 1);
    printf("\n");
}

void printAns() {

}

void stress() {

}

int main(){
#ifdef DEBUG
    freopen("in", "r", stdin);
    //freopen("out", "w", stdout);
#endif
    if (1) {
        int k = 1;
        for (int tt = 0; tt < k; tt++) {
            read();
            solve();
            printAns();
        }
    }
    else {
        stress();
    }

    return 0;
}


#include <iostream>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <cstring>
#include <queue>
#include <ctime>
#include <cassert>
#include <cstdio>
#include <algorithm>
#include <unordered_set>
#include <unordered_map>

using namespace std;

#define fr first
#define sc second
#define mp make_pair
#define pb push_back
#define epr(...) fprintf(stderr, __VA_ARGS__)

#define equal equalll
#define less lesss
const int N = 2e5 + 10;
const int INF = 1e9;

struct fraq {
    long long x, y;
    fraq() { }
    fraq(long long x) {
        y = 1;
        this->x = x;
    }
    fraq(long long x, long long y): x(x), y(y) {
        assert(y != 0);
        if (y < 0) {
            this->x *= -1;
            this->y *= -1;
        }
    }
    bool operator < (fraq other) {
        return x * other.y < other.x * y;
    }
    bool operator > (fraq other) {
        return x * other.y > other.x * y;
    }

    bool operator == (fraq other) {
        return x * other.y == other.x * y;
    }
    fraq operator * (fraq A) {
        return fraq(x * A.x, y * A.y);
    }
    fraq operator + (fraq A) {
        return fraq(x * A.y + A.x * y, y * A.y);
    }
    fraq operator - (fraq A) {
        return fraq(x * A.y - A.x * y, y * A.y);
    }
    void Epr() {
        epr("(%lld / %lld)\n", x, y);
        //epr("%lf\\c , x, y);
    }
};

struct pnt {
    fraq x, y;
    int id;
    pnt () { }
    pnt (fraq x, fraq y): x(x), y(y) { }
    pnt operator - (pnt A) {
        return pnt(x - A.x, y - A.y);
    }
    fraq operator * (pnt A) {
        return x * A.y - y * A.x;
    }
    fraq len2() {
        return x * x + y * y;
    }
    void Epr() {
        //cerr << "pnt x y:\n";
        epr("(%.3lf, %.3lf)\n", x.x * 1.0 / x.y, y.x * 1.0 / y.y);
        //x.Epr();
        //y.Epr();
    }
};

int n;
pnt p[N];
map < pair < int, int >, vector < int > > q;
pnt O;

void read() {
    scanf("%d", &n);
    int cur = 0;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        q[mp(x, y)].pb(i);
        if ((int)q[mp(x, y)].size() == 1)
            p[cur++] = pnt(fraq(1, x), fraq(1, y));
    }
    n = cur;
}

bool cmpO(pnt A, pnt B) {
    A = A - O;
    B = B - O;
    return A * B > 0 || (A * B == 0 && A.len2() < B.len2());
}

void convexHull() {
    for (int i = 0; i < n; i++)
        if (p[i].x < p[0].x || (p[0].x == p[i].x && p[i].y < p[0].y))
            swap(p[i], p[0]);

    O = p[0];
    sort(p + 1, p + n, cmpO);

    int cur = 0;
    for (int i = 0; i < n; i++) {
        for (; cur >= 2 && (p[cur - 1] - p[cur - 2]) * (p[i] - p[cur - 1]) < 0; cur--);
        p[cur++] = p[i];
    }
    n = cur;
    for (int i = 1; i < n; i++) {
        if (!(p[i].y < p[i - 1].y)) {
            n = i;
            break;
        }
    }
}

void solve() {
    convexHull();
    vector < int > res;
    for (int i = 0; i < n; i++) {
        auto pr = mp(p[i].x.y, p[i].y.y);
        vector < int > g = q[pr];
        for (auto x: g)
            res.pb(x);
    }
    sort(res.begin(), res.end());
    for (auto x: res)
        printf("%d ", x + 1);
    printf("\n");
}

void printAns() {

}

void stress() {

}

int main(){
#ifdef DEBUG
    freopen("in", "r", stdin);
    //freopen("out", "w", stdout);
#endif
    if (1) {
        int k = 1;
        for (int tt = 0; tt < k; tt++) {
            read();
            solve();
            printAns();
        }
    }
    else {
        stress();
    }

    return 0;
}


#include <iostream>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <string>
#include <cstring>
#include <queue>
#include <ctime>
#include <cassert>
#include <cstdio>
#include <algorithm>
#include <unordered_set>
#include <unordered_map>

using namespace std;

#define fr first
#define sc second
#define mp make_pair
#define pb push_back
#define epr(...) fprintf(stderr, __VA_ARGS__)

#define equal equalll
#define less lesss
const int N = 2e5 + 10;
const long long INF = 1e17;
const int T = 1e4;

bool equal(double a, double b) {
    return abs(a - b) < 1e-9;
}

bool less(double a, double b) {
    return a < b && !equal(a, b);
}

bool lessE(double a, double b) {
    return a < b || equal(a, b);
}

struct pnt {
    double x, y;
    int id;
    pnt () { }
    pnt (double x, double y): x(x), y(y) { }
    pnt operator - (pnt A) {
        return pnt(x - A.x, y - A.y);
    }
    pnt operator + (pnt A) {
        return pnt(x + A.x, y + A.y);
    }
    pnt operator * (double k) {
        return pnt(x * k, y * k);
    }
    double operator * (pnt A) {
        return x * A.y - y * A.x;
    }
    bool operator == (pnt A) {
        return equal(x, A.x) && equal(y, A.y);
    }
    bool operator != (pnt A) {
        return !equal(x, A.x) || !equal(y, A.y);
    }

    double len2() {
        return x * x + y * y;
    }
    void Epr() {
        int T = 1e4;
        epr("(%.5lf %.5lf)      \t\t real %d %d \n", x * T, y * T, (int)round(1 / x), (int)round(1 / y));
    }
};

int n;
pnt p[N];
map < pair < int, int >, vector < int > > q;
pair < int, int > in[N];
pnt O;

void read() {
    scanf("%d", &n);
    int cur = 0;
    for (int i = 0; i < n; i++) {
        int x, y;
        scanf("%d%d", &x, &y);
        in[i] = mp(x, y);
        q[mp(x, y)].pb(i);
        if ((int)q[mp(x, y)].size() == 1)
            p[cur++] = pnt(1.0 / x, 1.0 / y);
    }
    n = cur;
    for (int i = 0; i < n; i++)
        p[i] = p[i] * T;
    //cerr << "n: " << n << endl;
}

bool cmpO(pnt A, pnt B) {
    A = A - O;
    B = B - O;
    return less(0, A * B) || (equal(A * B, 0) && A.len2() < B.len2());
}

void convexHull() {
    for (int i = 0; i < n; i++)
        if (less(p[i].x, p[0].x) || (equal(p[0].x, p[i].x) && less(p[i].y, p[0].y)))
            swap(p[i], p[0]);

    O = p[0];
    sort(p + 1, p + n, cmpO);

    //int M = 10;
    //for (int i = 0; i < M; i++)
        //p[i].Epr();
    //vector < pnt > h;
    //for (int i = 0; i < n; i++)
        //h.pb(p[i]);
    //sort(p + 1, p + n, cmpO);
    //for (int i = 0; i < n; i++)
        //assert(p[i] == h[i]);

    int cur = 0;
    //cerr << "n: " << n << endl;
    for (int i = 0; i < n; i++) {
        for (; cur >= 2 && less((p[cur - 1] - p[cur - 2]) * (p[i] - p[cur - 1]), 0); cur--);
        p[cur++] = p[i];
        //for (;;) {
            //if (cur < 2) break;
            //pnt r1 = (p[cur - 1] - p[cur - 2]);
            //pnt r2 = (p[i] - p[cur - 1]);
            //double r3 = r1 * r2;
            //if (less(r3, 0)) {
                //cur--;
            //}
            //else
                //break;
        //}
        //p[cur++] = p[i];
    }
    //cerr << "cur: " << cur << endl;
    n = cur;
    for (int i = 1; i < n; i++) {
        if (lessE(p[i - 1].y, p[i].y)) {
            n = i;
            break;
        }
    }
}

void solve() {
    //for (int i = 0; i < n; i++)
        //for (int j = 0; j < n; j++) {
            //if (i == j) continue;
            ////cerr << "i j: " << i << " " << j << endl;
            //assert(p[i] != p[j]);
            ////assert(in[i] != in[j]);
        //}
    convexHull();
    vector < int > res;
    for (int i = 0; i < n; i++) {
        auto pr = mp((int)round(1 / p[i].x * T), (int)round(1 / p[i].y * T));
        assert((int)q[pr].size() > 0);
        vector < int > g = q[pr];
        for (auto x: g)
            res.pb(x);
        //for (auto x: g)
            //cerr << in[x].fr << " " << in[x].sc << endl;

    }
    sort(res.begin(), res.end());
    for (auto x: res)
        printf("%d ", x + 1);
    printf("\n");
    //cerr << clock() * 1.0 / CLOCKS_PER_SEC << endl;
    //cerr << "---\n";
}

void printAns() {

}

void stress() {

}

int main(){
#ifdef DEBUG
    freopen("in", "r", stdin);
    freopen("test.txt", "r", stdin);
    //freopen("out", "w", stdout);
#endif
    if (1) {
        int k = 1;
        for (int tt = 0; tt < k; tt++) {
            read();
            solve();
            printAns();
        }
    }
    else {
        stress();
    }

    return 0;
}


#include<bits/stdc++.h>
#define rep(i,k,n) for(int i= (int) k;i< (int) n;i++)
#define all(v) (v).begin(), (v).end()
#define pb push_back
#define ft first
#define sd second
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const long long inf = 9223372036854775807ll;
const int iinf = 2147483647;
const int limit = 1048576;
using namespace std;
bool sync_with_stdio (bool sync = false);

double eps = 1e-15;

bool sm(double a, double b) { return a < b + eps;}

struct Vect
{
    double x, y;
    Vect(double x, double y)
    :x{x}, y{y}
    {}
    Vect() = default;
};

std::ostream& operator <<(std::ostream& stream, const Vect& v)
{
    stream << v.x << " " << v.y;
    return stream;
}

Vect operator+(Vect v, Vect w){ return Vect(v.x + w.x, v.y + w.y);}
Vect operator-(Vect v, Vect w){ return Vect(v.x - w.x, v.y - w.y);}
double operator *(Vect v, Vect w){ return v.x * w.x + v.y * w.y; }
double det(Vect v, Vect w){ return v.x * w.y - w.x * v.y;}

struct Seg
{
    Vect beg, end;
    Seg(Vect beg, Vect end)
    :beg{beg}, end{end}
    {}
    Seg() = default;
};

std::ostream& operator <<(std::ostream& stream, const Seg& s)
{
    stream << s.beg << "  " << s.end;
    return stream;
}

Vect Lines_intersection(Seg a, Seg b)
{
    Vect v = Vect(a.beg.y - a.end.y, b.beg.y - b.end.y),
        w = Vect(a.end.x - a.beg.x, b.end.x - b.beg.x),
        c = Vect(a.end.x * a.beg.y - a.beg.x * a.end.y, b.end.x * b.beg.y - b.beg.x * b.end.y);
    return Vect(det(c, w) / det(v, w), det(v, c) / det(v, w));
}

int main(){
    int n; cin >> n;
    map<int, pair<int, int> > competitors;
    map<int, int> rev_competitors;
    vector<vector<int> > nums(limit);
    rep(i, 1, n + 1)
    {
        int s, r; cin >> s >> r;
        rev_competitors[r] = max(s, rev_competitors[r]);
        if(r == competitors[-s].ft)
        {
            nums[competitors[-s].sd].pb(i);
            continue;
        }
        nums[i].pb(i);
        competitors[-s] = max(competitors[-s], {r, i});
    }

    vector<pair<Seg, int> > poly_chain;
    Seg last_edge; int fastest_swimmer = 0;
    for(auto p : competitors)
    {
        if(rev_competitors[p.sd.ft] != -p.ft)
            continue;
        double s = -double(p.ft), r = double(p.sd.ft), i = p.sd.sd;
//         cout << s << " " << r << " " << i << "\n";
        Seg new_edge = Seg(Vect(0, 1/r), Vect(1, 1/r + 1/s));
//         cout << new_edge << "\n";
        if(fastest_swimmer == 0)
        {
            last_edge = new_edge; fastest_swimmer = i;
//             cout << "\n";
            continue;
        }

        bool done = false;
        while(poly_chain.size())
        {
            Seg edge; int j;
            tie(edge, j) = poly_chain.back();
//             cout << edge << "\n";
            Vect cross = Lines_intersection(new_edge, edge);
//             cout << cross << "\n";
            if(sm(cross.x, edge.beg.x))
            {
                done = true; break;
            }
            if(sm(cross.x, edge.end.x))
            {
                poly_chain.pop_back();
                poly_chain.pb({Seg(cross, edge.end), j});
                poly_chain.pb({Seg(new_edge.beg, cross), i});
                done = true; break;
            }
            poly_chain.pop_back();
        }
        if(!done)
        {
            Vect cross = Lines_intersection(new_edge, last_edge);
            if(sm(0.0, cross.x))
                poly_chain.pb({Seg(new_edge.beg, cross), i});
        }
//         cout << "\n";
    }
    vector<int> ans;
    for(auto j : nums[fastest_swimmer])
        ans.pb(j);
    for(auto p : poly_chain)
        for(auto j : nums[p.sd])
            ans.pb(j);
    sort(all(ans));
    for(auto i : ans)
        cout << i << " ";
    return 0;
}


#include<bits/stdc++.h>
#define rep(i,k,n) for(int i= (int) k;i< (int) n;i++)
#define all(v) (v).begin(), (v).end()
#define pb push_back
#define ft first
#define sd second
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const long long inf = 9223372036854775807ll;
const int iinf = 2147483647;
const int limit = 1048576;
using namespace std;
bool sync_with_stdio (bool sync = false);

struct Vect
{
    double x, y;
    Vect(double x, double y)
    :x{x}, y{y}
    {}
    Vect() = default;
};

std::ostream& operator <<(std::ostream& stream, const Vect& v)
{
    stream << v.x << " " << v.y;
    return stream;
}

Vect operator+(Vect v, Vect w){ return Vect(v.x + w.x, v.y + w.y);}
Vect operator-(Vect v, Vect w){ return Vect(v.x - w.x, v.y - w.y);}
double operator *(Vect v, Vect w){ return v.x * w.x + v.y * w.y; }
double det(Vect v, Vect w){ return v.x * w.y - w.x * v.y;}

struct Seg
{
    Vect beg, end;
    Seg(Vect beg, Vect end)
    :beg{beg}, end{end}
    {}
    Seg() = default;
};

std::ostream& operator <<(std::ostream& stream, const Seg& s)
{
    stream << s.beg << "  " << s.end;
    return stream;
}

Vect Lines_intersection(Seg a, Seg b)
{
    Vect v = Vect(a.beg.y - a.end.y, b.beg.y - b.end.y),
        w = Vect(a.end.x - a.beg.x, b.end.x - b.beg.x),
        c = Vect(a.end.x * a.beg.y - a.beg.x * a.end.y, b.end.x * b.beg.y - b.beg.x * b.end.y);
    return Vect(det(c, w) / det(v, w), det(v, c) / det(v, w));
}

int main(){
    int n; cin >> n;
    map<int, pair<int, int> > competitors;
    rep(i, 1, n + 1)
    {
        int s, r; cin >> s >> r;
        competitors[-s] = max(competitors[-s], {r, i});
    }

    vector<pair<Seg, int> > poly_chain;
    Seg last_edge; int fastest_swimmer = 0;
    for(auto p : competitors)
    {
        double s = -double(p.ft), r = double(p.sd.ft), i = p.sd.sd;
//         cout << s << " " << r << " " << i << "\n";
        Seg new_edge = Seg(Vect(0, 1/r), Vect(1, 1/r + 1/s));
//         cout << new_edge << "\n";
        if(fastest_swimmer == 0)
        {
            last_edge = new_edge; fastest_swimmer = i;
//             cout << "\n";
            continue;
        }

        bool done = false;
        while(poly_chain.size())
        {
            Seg edge; int j;
            tie(edge, j) = poly_chain.back();
//             cout << edge << "\n";
            Vect cross = Lines_intersection(new_edge, edge);
//             cout << cross << "\n";
            if(cross.x <= edge.beg.x)
            {
                done = true; break;
            }
            if(cross.x < edge.end.x)
            {
                poly_chain.pop_back();
                poly_chain.pb({Seg(cross, edge.end), j});
                poly_chain.pb({Seg(new_edge.beg, cross), i});
                done = true; break;
            }
            poly_chain.pop_back();
        }
        if(!done)
        {
            Vect cross = Lines_intersection(new_edge, last_edge);
            if(cross.x > 0.0)
                poly_chain.pb({Seg(new_edge.beg, cross), i});
        }
//         cout << "\n";
    }
    vector<int> ans = {fastest_swimmer};
    for(auto p : poly_chain)
        ans.pb(p.sd);
    sort(all(ans));
    for(auto i : ans)
        cout << i << " ";
    return 0;
}


#include<bits/stdc++.h>
#define rep(i,k,n) for(int i= (int) k;i< (int) n;i++)
#define all(v) (v).begin(), (v).end()
#define pb push_back
#define ft first
#define sd second
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const long long inf = 9223372036854775807ll;
const int iinf = 2147483647;
const int limit = 1048576;
using namespace std;
bool sync_with_stdio (bool sync = false);

struct Vect
{
    double x, y;
    Vect(double x, double y)
    :x{x}, y{y}
    {}
    Vect() = default;
};

std::ostream& operator <<(std::ostream& stream, const Vect& v)
{
    stream << v.x << " " << v.y;
    return stream;
}

Vect operator+(Vect v, Vect w){ return Vect(v.x + w.x, v.y + w.y);}
Vect operator-(Vect v, Vect w){ return Vect(v.x - w.x, v.y - w.y);}
double operator *(Vect v, Vect w){ return v.x * w.x + v.y * w.y; }
double det(Vect v, Vect w){ return v.x * w.y - w.x * v.y;}

struct Seg
{
    Vect beg, end;
    Seg(Vect beg, Vect end)
    :beg{beg}, end{end}
    {}
    Seg() = default;
};

std::ostream& operator <<(std::ostream& stream, const Seg& s)
{
    stream << s.beg << "  " << s.end;
    return stream;
}

Vect Lines_intersection(Seg a, Seg b)
{
    Vect v = Vect(a.beg.y - a.end.y, b.beg.y - b.end.y),
        w = Vect(a.end.x - a.beg.x, b.end.x - b.beg.x),
        c = Vect(a.end.x * a.beg.y - a.beg.x * a.end.y, b.end.x * b.beg.y - b.beg.x * b.end.y);
    return Vect(det(c, w) / det(v, w), det(v, c) / det(v, w));
}

int main(){
    int n; cin >> n;
    map<int, pair<int, int> > competitors;
    vector<vector<int> > nums(limit);
    rep(i, 1, n + 1)
    {
        int s, r; cin >> s >> r;
        if(r == competitors[-s].ft)
        {
            nums[competitors[-s].sd].pb(i);
            continue;
        }
        nums[i].pb(i);
        competitors[-s] = max(competitors[-s], {r, i});
    }

    vector<pair<Seg, int> > poly_chain;
    Seg last_edge; int fastest_swimmer = 0;
    for(auto p : competitors)
    {
        double s = -double(p.ft), r = double(p.sd.ft), i = p.sd.sd;
//         cout << s << " " << r << " " << i << "\n";
        Seg new_edge = Seg(Vect(0, 1/r), Vect(1, 1/r + 1/s));
//         cout << new_edge << "\n";
        if(fastest_swimmer == 0)
        {
            last_edge = new_edge; fastest_swimmer = i;
//             cout << "\n";
            continue;
        }

        bool done = false;
        while(poly_chain.size())
        {
            Seg edge; int j;
            tie(edge, j) = poly_chain.back();
//             cout << edge << "\n";
            Vect cross = Lines_intersection(new_edge, edge);
//             cout << cross << "\n";
            if(cross.x <= edge.beg.x)
            {
                done = true; break;
            }
            if(cross.x < edge.end.x)
            {
                poly_chain.pop_back();
                poly_chain.pb({Seg(cross, edge.end), j});
                poly_chain.pb({Seg(new_edge.beg, cross), i});
                done = true; break;
            }
            poly_chain.pop_back();
        }
        if(!done)
        {
            Vect cross = Lines_intersection(new_edge, last_edge);
            if(cross.x > 0.0)
                poly_chain.pb({Seg(new_edge.beg, cross), i});
        }
//         cout << "\n";
    }
    vector<int> ans = {fastest_swimmer};
    for(auto p : poly_chain)
        for(auto j : nums[p.sd])
            ans.pb(j);
    sort(all(ans));
    for(auto i : ans)
        cout << i << " ";
    return 0;
}


#include<bits/stdc++.h>
#define rep(i,k,n) for(int i= (int) k;i< (int) n;i++)
#define all(v) (v).begin(), (v).end()
#define pb push_back
#define ft first
#define sd second
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const long long inf = 9223372036854775807ll;
const int iinf = 2147483647;
const int limit = 1048576;
using namespace std;
bool sync_with_stdio (bool sync = false);

struct Vect
{
    double x, y;
    Vect(double x, double y)
    :x{x}, y{y}
    {}
    Vect() = default;
};

std::ostream& operator <<(std::ostream& stream, const Vect& v)
{
    stream << v.x << " " << v.y;
    return stream;
}

Vect operator+(Vect v, Vect w){ return Vect(v.x + w.x, v.y + w.y);}
Vect operator-(Vect v, Vect w){ return Vect(v.x - w.x, v.y - w.y);}
double operator *(Vect v, Vect w){ return v.x * w.x + v.y * w.y; }
double det(Vect v, Vect w){ return v.x * w.y - w.x * v.y;}

struct Seg
{
    Vect beg, end;
    Seg(Vect beg, Vect end)
    :beg{beg}, end{end}
    {}
    Seg() = default;
};

std::ostream& operator <<(std::ostream& stream, const Seg& s)
{
    stream << s.beg << "  " << s.end;
    return stream;
}

Vect Lines_intersection(Seg a, Seg b)
{
    Vect v = Vect(a.beg.y - a.end.y, b.beg.y - b.end.y),
        w = Vect(a.end.x - a.beg.x, b.end.x - b.beg.x),
        c = Vect(a.end.x * a.beg.y - a.beg.x * a.end.y, b.end.x * b.beg.y - b.beg.x * b.end.y);
    return Vect(det(c, w) / det(v, w), det(v, c) / det(v, w));
}

int main(){
    int n; cin >> n;
    map<int, pair<int, int> > competitors;
    vector<vector<int> > nums(limit);
    rep(i, 1, n + 1)
    {
        int s, r; cin >> s >> r;
        if(r == competitors[-s].ft)
        {
            nums[competitors[-s].sd].pb(i);
            continue;
        }
        nums[i].pb(i);
        competitors[-s] = max(competitors[-s], {r, i});
    }

    vector<pair<Seg, int> > poly_chain;
    Seg last_edge; int fastest_swimmer = 0;
    for(auto p : competitors)
    {
        double s = -double(p.ft), r = double(p.sd.ft), i = p.sd.sd;
//         cout << s << " " << r << " " << i << "\n";
        Seg new_edge = Seg(Vect(0, 1/r), Vect(1, 1/r + 1/s));
//         cout << new_edge << "\n";
        if(fastest_swimmer == 0)
        {
            last_edge = new_edge; fastest_swimmer = i;
//             cout << "\n";
            continue;
        }

        bool done = false;
        while(poly_chain.size())
        {
            Seg edge; int j;
            tie(edge, j) = poly_chain.back();
//             cout << edge << "\n";
            Vect cross = Lines_intersection(new_edge, edge);
//             cout << cross << "\n";
            if(cross.x <= edge.beg.x)
            {
                done = true; break;
            }
            if(cross.x < edge.end.x)
            {
                poly_chain.pop_back();
                poly_chain.pb({Seg(cross, edge.end), j});
                poly_chain.pb({Seg(new_edge.beg, cross), i});
                done = true; break;
            }
            poly_chain.pop_back();
        }
        if(!done)
        {
            Vect cross = Lines_intersection(new_edge, last_edge);
            if(cross.x > 0.0)
                poly_chain.pb({Seg(new_edge.beg, cross), i});
        }
//         cout << "\n";
    }
    vector<int> ans;
    for(auto j : nums[fastest_swimmer])
        ans.pb(j);
    for(auto p : poly_chain)
        for(auto j : nums[p.sd])
            ans.pb(j);
    sort(all(ans));
    for(auto i : ans)
        cout << i << " ";
    return 0;
}


#include<bits/stdc++.h>
#define rep(i,k,n) for(int i= (int) k;i< (int) n;i++)
#define all(v) (v).begin(), (v).end()
#define pb push_back
#define ft first
#define sd second
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const long long inf = 9223372036854775807ll;
const int iinf = 2147483647;
const int limit = 1048576;
using namespace std;
bool sync_with_stdio (bool sync = false);

struct Vect
{
    double x, y;
    Vect(double x, double y)
    :x{x}, y{y}
    {}
    Vect() = default;
};

std::ostream& operator <<(std::ostream& stream, const Vect& v)
{
    stream << v.x << " " << v.y;
    return stream;
}

Vect operator+(Vect v, Vect w){ return Vect(v.x + w.x, v.y + w.y);}
Vect operator-(Vect v, Vect w){ return Vect(v.x - w.x, v.y - w.y);}
double operator *(Vect v, Vect w){ return v.x * w.x + v.y * w.y; }
double det(Vect v, Vect w){ return v.x * w.y - w.x * v.y;}

struct Seg
{
    Vect beg, end;
    Seg(Vect beg, Vect end)
    :beg{beg}, end{end}
    {}
    Seg() = default;
};

std::ostream& operator <<(std::ostream& stream, const Seg& s)
{
    stream << s.beg << "  " << s.end;
    return stream;
}

Vect Lines_intersection(Seg a, Seg b)
{
    Vect v = Vect(a.beg.y - a.end.y, b.beg.y - b.end.y),
        w = Vect(a.end.x - a.beg.x, b.end.x - b.beg.x),
        c = Vect(a.end.x * a.beg.y - a.beg.x * a.end.y, b.end.x * b.beg.y - b.beg.x * b.end.y);
    return Vect(det(c, w) / det(v, w), det(v, c) / det(v, w));
}

int main(){
    int n; cin >> n;
    map<int, pair<int, int> > competitors;
    rep(i, 1, n + 1)
    {
        int s, r; cin >> s >> r;
        competitors[-s] = max(competitors[-s], {r, i});
    }

    vector<pair<Seg, int> > poly_chain;
    Seg last_edge; int fastest_swimmer = 0;
    for(auto p : competitors)
    {
        double s = -double(p.ft), r = double(p.sd.ft), i = p.sd.sd;
//         cout << s << " " << r << " " << i << "\n";
        Seg new_edge = Seg(Vect(0, 1/r), Vect(1, 1/r + 1/s));
//         cout << new_edge << "\n";
        if(fastest_swimmer == 0)
        {
            last_edge = new_edge; fastest_swimmer = i;
//             cout << "\n";
            continue;
        }

        bool done = false;
        while(poly_chain.size())
        {
            Seg edge; int j;
            tie(edge, j) = poly_chain.back(); poly_chain.pop_back();
//             cout << edge << "\n";
            Vect cross = Lines_intersection(new_edge, edge);
//             cout << cross << "\n";
            if(cross.x <= edge.beg.x)
            {
                done = true; break;
            }
            if(cross.x < edge.end.x)
            {
                poly_chain.pb({Seg(cross, edge.end), j});
                poly_chain.pb({Seg(new_edge.beg, cross), i});
                done = true; break;
            }
        }
        if(!done)
        {
            Vect cross = Lines_intersection(new_edge, last_edge);
            poly_chain.pb({Seg(new_edge.beg, cross), i});
        }
//         cout << "\n";
    }
    vector<int> ans = {fastest_swimmer};
    for(auto p : poly_chain)
        ans.pb(p.sd);
    sort(all(ans));
    for(auto i : ans)
        cout << i << " ";
    return 0;
}


#include<bits/stdc++.h>
#define rep(i,k,n) for(int i= (int) k;i< (int) n;i++)
#define all(v) (v).begin(), (v).end()
#define pb push_back
#define ft first
#define sd second
typedef long long ll;
typedef unsigned long long ull;
typedef long double ld;
const long long inf = 9223372036854775807ll;
const int iinf = 2147483647;
const int limit = 1048576;
using namespace std;
bool sync_with_stdio (bool sync = false);

double eps = 1e-15;

bool sm(double a, double b) { return a < b + eps;}

struct Vect
{
    double x, y;
    Vect(double x, double y)
    :x{x}, y{y}
    {}
    Vect() = default;
};

std::ostream& operator <<(std::ostream& stream, const Vect& v)
{
    stream << v.x << " " << v.y;
    return stream;
}

Vect operator+(Vect v, Vect w){ return Vect(v.x + w.x, v.y + w.y);}
Vect operator-(Vect v, Vect w){ return Vect(v.x - w.x, v.y - w.y);}
double operator *(Vect v, Vect w){ return v.x * w.x + v.y * w.y; }
double det(Vect v, Vect w){ return v.x * w.y - w.x * v.y;}

struct Seg
{
    Vect beg, end;
    Seg(Vect beg, Vect end)
    :beg{beg}, end{end}
    {}
    Seg() = default;
};

std::ostream& operator <<(std::ostream& stream, const Seg& s)
{
    stream << s.beg << "  " << s.end;
    return stream;
}

Vect Lines_intersection(Seg a, Seg b)
{
    Vect v = Vect(a.beg.y - a.end.y, b.beg.y - b.end.y),
        w = Vect(a.end.x - a.beg.x, b.end.x - b.beg.x),
        c = Vect(a.end.x * a.beg.y - a.beg.x * a.end.y, b.end.x * b.beg.y - b.beg.x * b.end.y);
    return Vect(det(c, w) / det(v, w), det(v, c) / det(v, w));
}

int main(){
    int n; cin >> n;
    map<int, pair<int, int> > competitors;
    vector<vector<int> > nums(limit);
    rep(i, 1, n + 1)
    {
        int s, r; cin >> s >> r;
        if(r == competitors[-s].ft)
        {
            nums[competitors[-s].sd].pb(i);
            continue;
        }
        nums[i].pb(i);
        competitors[-s] = max(competitors[-s], {r, i});
    }

    vector<pair<Seg, int> > poly_chain;
    Seg last_edge; int fastest_swimmer = 0;
    for(auto p : competitors)
    {
        double s = -double(p.ft), r = double(p.sd.ft), i = p.sd.sd;
//         cout << s << " " << r << " " << i << "\n";
        Seg new_edge = Seg(Vect(0, 1/r), Vect(1, 1/r + 1/s));
//         cout << new_edge << "\n";
        if(fastest_swimmer == 0)
        {
            last_edge = new_edge; fastest_swimmer = i;
//             cout << "\n";
            continue;
        }

        bool done = false;
        while(poly_chain.size())
        {
            Seg edge; int j;
            tie(edge, j) = poly_chain.back();
//             cout << edge << "\n";
            Vect cross = Lines_intersection(new_edge, edge);
//             cout << cross << "\n";
            if(sm(cross.x, edge.beg.x))
            {
                done = true; break;
            }
            if(sm(cross.x, edge.end.x))
            {
                poly_chain.pop_back();
                poly_chain.pb({Seg(cross, edge.end), j});
                poly_chain.pb({Seg(new_edge.beg, cross), i});
                done = true; break;
            }
            poly_chain.pop_back();
        }
        if(!done)
        {
            Vect cross = Lines_intersection(new_edge, last_edge);
            if(sm(0.0, cross.x))
                poly_chain.pb({Seg(new_edge.beg, cross), i});
        }
//         cout << "\n";
    }
    vector<int> ans;
    for(auto j : nums[fastest_swimmer])
        ans.pb(j);
    for(auto p : poly_chain)
        for(auto j : nums[p.sd])
            ans.pb(j);
    sort(all(ans));
    for(auto i : ans)
        cout << i << " ";
    return 0;
}


#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>

using namespace std;

typedef long long ll;

ll gcd(ll a, ll b) {return b == 0 ? a : gcd(b, a % b);}
struct Rat {
    ll p, q;
    Rat() {}
    Rat(ll x, ll y) {
        p = x, q = y;
        if(p == 0) q = 1;
        else if(q == 0) p = 1;
        else {
            ll g = gcd(abs(p),abs(q));
            if(q < 0) g *= -1;
            p /= g, q /= g;
        }
    }
    bool operator == (const Rat &a) const {
        return p * a.q == a.p * q;
    }
    Rat operator + (const ll &x) const {
        return Rat(p + x * q, q);
    }
    Rat operator * (const ll &x) const {
        if(p == 0 || x == 0) return Rat(0, 1);
        ll g = gcd(abs(x), abs(q));
        return Rat(p * (x / g), q / g);
    }
    Rat operator + (const Rat &a) const {
        if(p == 0) return a;
        if(a.p == 0) return Rat(p, q);
        ll g = 1;
        return Rat(p * (a.q / g) + a.p * (q / g), q / g * a.q);
    }
    Rat operator - (const Rat &a) const {
    	Rat tmp = a; tmp.p *= -1;
	return *this + tmp;
    }
    Rat operator * (const Rat &a) const {
    	if(p == 0 || a.p == 0) return Rat(0, 1);
	ll np = p * a.p, nq = q * a.q;
	ll g = 1;
	return Rat(np / g, nq / g);
    }
    bool operator < (const Rat &a) const {
    	return p * a.q < a.p * q;
    }
};

struct point {
    Rat x,y;
    int idx;
    point() {}
    void read(int i) {
    	idx = i;
    	int s,r; scanf("%d%d",&s,&r);
	x = Rat(1,s), y = Rat(1,r);
    }
} P[200005];

Rat sqr(Rat x) {return x*x;}

int ccw(const point &p1, const point &p2, const point &p3) {
    Rat ret = (p2.x - p1.x)*(p3.y - p1.y) - (p2.y - p1.y)*(p3.x - p1.x);
    if(ret.p == 0) return 0;
    return ret.p > 0 ? 1 : -1;
}

bool cmp(const point &a, const point &b) {
    int c=ccw(P[0],a,b);
    if(c==0) return sqr(P[0].x-a.x)+sqr(P[0].y-a.y)<sqr(P[0].x-b.x)+sqr(P[0].y-b.y);
    return c>0;
}

int st[200005],sz;
int n;

int main() {
    scanf("%d",&n);
    Rat my=Rat(10000,1),mx=Rat(10000,1);
    int idx=-1;
    for(int i=0;i<n;++i) {
        P[i].read(i);
        if(P[i].y<my || P[i].y==my&&P[i].x<mx) my=P[i].y,mx=P[i].x,idx=i;
    }
    swap(P[0],P[idx]);
    sort(P+1,P+n,cmp);
    st[0]=0,st[1]=1,sz=2;
    for(int i=2;i<n;++i) {
        while(sz>=2 && ccw(P[st[sz-2]],P[st[sz-1]],P[i])<0) {
            sz--;
        } st[sz++]=i;
    }

    vector<int> ans;
    Rat my2=Rat(10000,1),mx2=Rat(10000,1);
    int idx2=-1;
    for(int i=0;i<sz;++i) {
    	int j = st[i];
        if(P[j].x<mx2 || P[j].x==mx2&&P[j].y<my2) mx2=P[j].x,my2=P[j].y,idx2=i;
    }
    for(int i=idx2;i<sz;++i) {
    	ans.push_back(P[st[i]].idx);
    } ans.push_back(P[st[0]].idx);

    sort(ans.begin(), ans.end());
    for(int i=0;i<ans.size();++i) printf("%d ",ans[i]+1);
}


#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>

using namespace std;

typedef long long ll;

ll gcd(ll a, ll b) {return b == 0 ? a : gcd(b, a % b);}
struct Rat {
    ll p, q;
    Rat() {}
    Rat(ll x, ll y) {
        p = x, q = y;
        if(p == 0) q = 1;
        else if(q == 0) p = 1;
        else {
            ll g = 1;
            if(q < 0) g *= -1;
            p /= g, q /= g;
        }
    }
    bool operator == (const Rat &a) const {
        return p * a.q == a.p * q;
    }
    Rat operator + (const ll &x) const {
        return Rat(p + x * q, q);
    }
    Rat operator * (const ll &x) const {
        if(p == 0 || x == 0) return Rat(0, 1);
        ll g = gcd(abs(x), abs(q));
        return Rat(p * (x / g), q / g);
    }
    Rat operator + (const Rat &a) const {
        if(p == 0) return a;
        if(a.p == 0) return Rat(p, q);
        ll g = 1;
        return Rat(p * (a.q / g) + a.p * (q / g), q / g * a.q);
    }
    Rat operator - (const Rat &a) const {
    	Rat tmp = a; tmp.p *= -1;
	return *this + tmp;
    }
    Rat operator * (const Rat &a) const {
    	if(p == 0 || a.p == 0) return Rat(0, 1);
	ll np = p * a.p, nq = q * a.q;
	ll g = 1;
	return Rat(np / g, nq / g);
    }
    bool operator < (const Rat &a) const {
    	return p * a.q < a.p * q;
    }
};

struct point {
    Rat x,y;
    int idx;
    point() {}
    void read(int i) {
    	idx = i;
    	int s,r; scanf("%d%d",&s,&r);
	x = Rat(1,s), y = Rat(1,r);
    }
} P[200005];

Rat sqr(Rat x) {return x*x;}

int ccw(const point &p1, const point &p2, const point &p3) {
    Rat ret = (p2.x - p1.x)*(p3.y - p1.y) - (p2.y - p1.y)*(p3.x - p1.x);
    if(ret.p == 0) return 0;
    return ret.p > 0 ? 1 : -1;
}

bool cmp(const point &a, const point &b) {
    int c=ccw(P[0],a,b);
    if(c==0) return sqr(P[0].x-a.x)+sqr(P[0].y-a.y)<sqr(P[0].x-b.x)+sqr(P[0].y-b.y);
    return c>0;
}

int st[200005],sz;
int n;

int main() {
    scanf("%d",&n);
    Rat my=Rat(10000,1),mx=Rat(10000,1);
    int idx=-1;
    for(int i=0;i<n;++i) {
        P[i].read(i);
        if(P[i].y<my || P[i].y==my&&P[i].x<mx) my=P[i].y,mx=P[i].x,idx=i;
    }
    swap(P[0],P[idx]);
    sort(P+1,P+n,cmp);
    st[0]=0,st[1]=1,sz=2;
    for(int i=2;i<n;++i) {
        while(sz>=2 && ccw(P[st[sz-2]],P[st[sz-1]],P[i])<=0) {
            sz--;
        } st[sz++]=i;
    }

    vector<int> ans;
    Rat my2=Rat(10000,1),mx2=Rat(10000,1);
    int idx2=-1;
    for(int i=0;i<sz;++i) {
    	int j = st[i];
        if(P[j].x<mx2 || P[j].x==mx2&&P[j].y<my2) mx2=P[j].x,my2=P[j].y,idx2=i;
    }
    for(int i=idx2;i<sz;++i) {
    	ans.push_back(P[st[i]].idx);
    } ans.push_back(P[st[0]].idx);

    sort(ans.begin(), ans.end());
    for(int i=0;i<ans.size();++i) printf("%d ",ans[i]+1);
}


#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>

using namespace std;

typedef long long ll;

ll gcd(ll a, ll b) {return b == 0 ? a : gcd(b, a % b);}
struct Rat {
    ll p, q;
    Rat() {}
    Rat(ll x, ll y) {
        p = x, q = y;
        if(p == 0) q = 1;
        else if(q == 0) p = 1;
        else {
            ll g = 1;
            if(q < 0) g *= -1;
            p /= g, q /= g;
        }
    }
    bool operator == (const Rat &a) const {
        return p * a.q == a.p * q;
    }
    Rat operator + (const ll &x) const {
        return Rat(p + x * q, q);
    }
    Rat operator * (const ll &x) const {
        if(p == 0 || x == 0) return Rat(0, 1);
        ll g = gcd(abs(x), abs(q));
        return Rat(p * (x / g), q / g);
    }
    Rat operator + (const Rat &a) const {
        if(p == 0) return a;
        if(a.p == 0) return Rat(p, q);
        ll g = 1;
        return Rat(p * (a.q / g) + a.p * (q / g), q / g * a.q);
    }
    Rat operator - (const Rat &a) const {
    	Rat tmp = a; tmp.p *= -1;
	return *this + tmp;
    }
    Rat operator * (const Rat &a) const {
    	if(p == 0 || a.p == 0) return Rat(0, 1);
	ll np = p * a.p, nq = q * a.q;
	ll g = 1;
	return Rat(np / g, nq / g);
    }
    bool operator < (const Rat &a) const {
    	return p * a.q < a.p * q;
    }
};

struct point {
    Rat x,y;
    int idx;
    point() {}
    void read(int i) {
    	idx = i;
    	int s,r; scanf("%d%d",&s,&r);
	x = Rat(1,s), y = Rat(1,r);
    }
} P[200005];

Rat sqr(Rat x) {return x*x;}

int ccw(const point &p1, const point &p2, const point &p3) {
    Rat ret = (p2.x - p1.x)*(p3.y - p1.y) - (p2.y - p1.y)*(p3.x - p1.x);
    if(ret.p == 0) return 0;
    return ret.p > 0 ? 1 : -1;
}

bool cmp(const point &a, const point &b) {
    int c=ccw(P[0],a,b);
    if(c==0) return sqr(P[0].x-a.x)+sqr(P[0].y-a.y)<sqr(P[0].x-b.x)+sqr(P[0].y-b.y);
    return c>0;
}

int st[200005],sz;
int n;

int main() {
    scanf("%d",&n);
    Rat my=Rat(10000,1),mx=Rat(10000,1);
    int idx=-1;
    for(int i=0;i<n;++i) {
        P[i].read(i);
        if(P[i].y<my || P[i].y==my&&P[i].x<mx) my=P[i].y,mx=P[i].x,idx=i;
    }
    swap(P[0],P[idx]);
    sort(P+1,P+n,cmp);
    st[0]=0,st[1]=1,sz=2;
    for(int i=2;i<n;++i) {
        while(sz>=2 && ccw(P[st[sz-2]],P[st[sz-1]],P[i])>0) {
            sz--;
        } st[sz++]=i;
    }

    vector<int> ans;
    Rat my2=Rat(10000,1),mx2=Rat(10000,1);
    int idx2=-1;
    for(int i=0;i<sz;++i) {
    	int j = st[i];
        if(P[j].x<mx2 || P[j].x==mx2&&P[j].y<my2) mx2=P[j].x,my2=P[j].y,idx2=i;
    }
    for(int i=idx2;i<sz;++i) {
    	ans.push_back(P[st[i]].idx);
    } ans.push_back(P[st[0]].idx);

    sort(ans.begin(), ans.end());
    for(int i=0;i<ans.size();++i) printf("%d ",ans[i]+1);
}


#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cmath>

using namespace std;

struct point {
    double x,y;
    int idx;
    point() {}
    void read(int i) {
    	idx = i;
    	int s,r; scanf("%d%d",&s,&r);
	x = 1.0 / s, y = 1.0 / r;
    }
} P[200005];

double sqr(double x) {return x*x;}
const double eps = 1e-12;

int ccw(const point &p1, const point &p2, const point &p3) {
    double ret = (p2.x - p1.x)*(p3.y - p1.y) - (p2.y - p1.y)*(p3.x - p1.x);
    if(abs(ret) < eps) return 0;
    return ret > 0 ? 1 : -1;
}

bool cmp(const point &a, const point &b) {
    int c=ccw(P[0],a,b);
    if(c==0) return sqr(P[0].x-a.x)+sqr(P[0].y-a.y)<sqr(P[0].x-b.x)+sqr(P[0].y-b.y);
    return c>0;
}

int st[200005],sz;
int n;

int main() {
    scanf("%d",&n);
    double my = 1e10, mx = 1e10;
    int idx=-1;
    for(int i=0;i<n;++i) {
        P[i].read(i);
        if(P[i].y<my || P[i].y==my&&P[i].x<mx) my=P[i].y,mx=P[i].x,idx=i;
    }
    swap(P[0],P[idx]);
    sort(P+1,P+n,cmp);
    st[0]=0,st[1]=1,sz=2;
    for(int i=2;i<n;++i) {
        while(sz>=2 && ccw(P[st[sz-2]],P[st[sz-1]],P[i])<0) {
            sz--;
        } st[sz++]=i;
    }

    vector<int> ans;
    double my2 = 1e10, mx2 = 1e10;
    int idx2=-1;
    for(int i=0;i<sz;++i) {
    	int j = st[i];
        if(P[j].x<mx2 || P[j].x==mx2&&P[j].y<my2) mx2=P[j].x,my2=P[j].y,idx2=i;
    }
    for(int i=idx2;i<sz;++i) {
    	ans.push_back(P[st[i]].idx);
    } ans.push_back(P[st[0]].idx);

    sort(ans.begin(), ans.end());
    for(int i=0;i<ans.size();++i) printf("%d ",ans[i]+1);
}


#include<cstdio>
#include<algorithm>
#include<vector>
#include<string>
#include<cstring>

using namespace std;
int F[333];
void Build(const string &pattern) {
    int m = pattern.size(), i, j;
    F[0] = F[1] = 0; // always true
    for(i = 2; i <= m; i++)    {
        j = F[i - 1];
        for( ; ; ) {
            if(pattern[j] == pattern[i - 1])
                { F[i] = j + 1; break; }
            if(j == 0) { F[i] = 0; break; }
            j = F[j];
        }
    }
}

vector<int> KMP(const string &pattern, const string &text) {
    Build(pattern);
    int n = text.size(), m = pattern.size();
    int i = 0; // the initial state of the automaton is
    int j = 0; // the first character of the text
    vector<int> res;
    for( ; ; ) {
        if(j == n) break; // we reached the end of the text
        if(text[j] == pattern[i]) {
            i++; // change the state of the automaton
            j++; // get the next character from the text
            if(i == m) res.push_back(j-i);// match found at j - i
        }
        else if(i > 0) i = F[i]; /*!!!!! when you use KMP as a part of dp, you should modify this part recursively */
        else j++;
    } return res;
}

const int mod = 1000*1000*1000+7;
int n,m,p;
char str[1000005];
char pat[1000005];
int y[1000005],mat[1000005];
string patS,strS;

int main() {
	scanf("%d%d%s",&n,&m,pat), p = strlen(pat);
	for(int i=0;i<m;++i) scanf("%d",y+i),y[i]--,mat[y[i]]=1;
	memset(str,'?',sizeof(str)), str[n] = 0;
	for(int i=0,cur=0;i<n;++i) if(mat[i]) {
		for(int j=max(0,cur-i);j<p&&i+j<n;++j) str[i+j] = pat[j];
		cur = max(cur, i+p);
	} patS = pat, strS = str;

	Build(patS);
	vector<int> res = KMP(patS,strS);
	bool no = (res.size() != m);
	for(int i=0;i<min((int)res.size(),m);++i) if(res[i] != y[i]) no = 1;
	if(no) printf("0");
	else {
		int c = count(str,str+n,'?');
		int ans = 1;
		while(c) ans = (long long)ans * 26 % mod, c--;
		printf("%d",ans);
	}
}


#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>

using namespace std;

map< pair<int,int>, vector<int> > idxs;

struct point {
    double x,y;
    int s,r;
    point() {}
    bool read(int i) {
    	int ss,rr; scanf("%d%d",&ss,&rr);
	s = ss, r = rr;
	x = 1.0 / s, y = 1.0 / r;
	bool ck = 1;
	if(idxs.count(make_pair(s,r))) ck = 0;
	idxs[make_pair(s,r)].push_back(i);
	return ck;
    }
    bool operator == (const point &rhs) const {
    	return s == rhs.s && r == rhs.r;
    }
};

double sqr(double x) {return x*x;}
const double eps = 1e-22;

int ccw(const point &p1, const point &p2, const point &p3) {
    double ret = (p2.x - p1.x)*(p3.y - p1.y) - (p2.y - p1.y)*(p3.x - p1.x);
    if(abs(ret) < eps) return 0;
    return ret > 0 ? 1 : -1;
}

vector<point> V;
vector<int> ans;
point mX,mY;

bool cmp(const point &a, const point &b) {
    int c=ccw(mY,a,b);
    if(c==0) return sqr(mY.x-a.x)+sqr(mY.y-a.y)<sqr(mY.x-b.x)+sqr(mY.y-b.y);
    return c<0;
}
bool cmpx(const point &a, const point &b) {
	return make_pair(a.s, a.r) > make_pair(b.s, b.r);
}
bool cmpy(const point &a, const point &b) {
	return make_pair(a.r, a.s) > make_pair(b.r, b.s);
}

int st[200005],sz;
int n;

int main() {
    scanf("%d",&n);
    for(int i=0;i<n;++i) {
        point P;
	if(P.read(i)) V.push_back(P);
    }
    mX = *min_element(V.begin(),V.end(),cmpx);
    mY = *min_element(V.begin(),V.end(),cmpy);
    sort(V.begin(),V.end(),cmp);
    st[0] = 0, sz++;
    if(!(mX == mY)) {
	st[sz++] = 1;
	for(int i=2;i<V.size();++i) {
	    if(V[st[sz-1]] == mX) break;
	    while(sz>=2 && ccw(V[st[sz-2]],V[st[sz-1]],V[i])>0) {
    	        sz--;
    	    } st[sz++]=i;
    	}
    }

    for(int i=0;i<sz;++i) {
    	for(auto x : idxs[make_pair(V[st[i]].s,V[st[i]].r)])
    		ans.push_back(x);
    }

    sort(ans.begin(), ans.end());
    for(int i=0;i<ans.size();++i) printf("%d ",ans[i]+1);
}


#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>

using namespace std;

typedef long long ll;

ll gcd(ll a, ll b) {return b == 0 ? a : gcd(b, a % b);}
struct Rat {
    ll p, q;
    Rat() {}
    Rat(ll x, ll y) {
        p = x, q = y;
        if(p == 0) q = 1;
        else if(q == 0) p = 1;
        else {
            ll g = 1;
            if(q < 0) g *= -1;
            p /= g, q /= g;
        }
    }
    bool operator == (const Rat &a) const {
        return p * a.q == a.p * q;
    }
    Rat operator + (const ll &x) const {
        return Rat(p + x * q, q);
    }
    Rat operator * (const ll &x) const {
        if(p == 0 || x == 0) return Rat(0, 1);
        ll g = gcd(abs(x), abs(q));
        return Rat(p * (x / g), q / g);
    }
    Rat operator + (const Rat &a) const {
        if(p == 0) return a;
        if(a.p == 0) return Rat(p, q);
        ll g = 1;
        return Rat(p * (a.q / g) + a.p * (q / g), q / g * a.q);
    }
    Rat operator - (const Rat &a) const {
    	Rat tmp = a; tmp.p *= -1;
	return *this + tmp;
    }
    Rat operator * (const Rat &a) const {
    	if(p == 0 || a.p == 0) return Rat(0, 1);
	ll np = p * a.p, nq = q * a.q;
	ll g = 1;
	return Rat(np / g, nq / g);
    }
    bool operator < (const Rat &a) const {
    	return p * a.q < a.p * q;
    }
};

struct point {
    Rat x,y;
    int idx;
    point() {}
    void read(int i) {
    	idx = i;
    	int s,r; scanf("%d%d",&s,&r);
	x = Rat(1,s), y = Rat(1,r);
    }
} P[200005];

Rat sqr(Rat x) {return x*x;}

int ccw(const point &p1, const point &p2, const point &p3) {
    Rat ret = (p2.x - p1.x)*(p3.y - p1.y) - (p2.y - p1.y)*(p3.x - p1.x);
    if(ret.p == 0) return 0;
    return ret.p > 0 ? 1 : -1;
}

bool cmp(const point &a, const point &b) {
    int c=ccw(P[0],a,b);
    if(c==0) return sqr(P[0].x-a.x)+sqr(P[0].y-a.y)<sqr(P[0].x-b.x)+sqr(P[0].y-b.y);
    return c>0;
}

int st[200005],sz;
int n;

int main() {
    scanf("%d",&n);
    Rat my=Rat(10000,1),mx=Rat(10000,1);
    int idx=-1;
    for(int i=0;i<n;++i) {
        P[i].read(i);
        if(P[i].y<my || P[i].y==my&&P[i].x<mx) my=P[i].y,mx=P[i].x,idx=i;
    }
    swap(P[0],P[idx]);
    sort(P+1,P+n,cmp);
    st[0]=0,st[1]=1,sz=2;
    for(int i=2;i<n;++i) {
        while(sz>=2 && ccw(P[st[sz-2]],P[st[sz-1]],P[i])<0) {
            sz--;
        } st[sz++]=i;
    }

    vector<int> ans;
    Rat my2=Rat(10000,1),mx2=Rat(10000,1);
    int idx2=-1;
    for(int i=0;i<sz;++i) {
    	int j = st[i];
        if(P[j].x<mx2 || P[j].x==mx2&&P[j].y<my2) mx2=P[j].x,my2=P[j].y,idx2=i;
    }
    for(int i=idx2;i<sz;++i) {
    	ans.push_back(P[st[i]].idx);
    } ans.push_back(P[st[0]].idx);

    sort(ans.begin(), ans.end());
    for(int i=0;i<ans.size();++i) printf("%d ",ans[i]+1);
}


#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>

using namespace std;

map< pair<int,int>, vector<int> > idxs;

struct point {
    double x,y;
    int s,r;
    point() {}
    bool read(int i) {
    	int ss,rr; scanf("%d%d",&ss,&rr);
	s = ss, r = rr;
	x = 1.0 / s, y = 1.0 / r;
	bool ck = 1;
	if(idxs.count(make_pair(s,r))) ck = 0;
	idxs[make_pair(s,r)].push_back(i);
	return ck;
    }
    bool operator == (const point &rhs) const {
    	return s == rhs.s && r == rhs.r;
    }
};

double sqr(double x) {return x*x;}
const double eps = 1e-12;

int ccw(const point &p1, const point &p2, const point &p3) {
    double ret = (p2.x - p1.x)*(p3.y - p1.y) - (p2.y - p1.y)*(p3.x - p1.x);
    if(abs(ret) < eps) return 0;
    return ret > 0 ? 1 : -1;
}

vector<point> V;
vector<int> ans;
point mX,mY;

bool cmp(const point &a, const point &b) {
    int c=ccw(mY,a,b);
    if(c==0) return sqr(mY.x-a.x)+sqr(mY.y-a.y)<sqr(mY.x-b.x)+sqr(mY.y-b.y);
    return c<0;
}
bool cmpx(const point &a, const point &b) {
	return make_pair(a.s, a.r) > make_pair(b.s, b.r);
}
bool cmpy(const point &a, const point &b) {
	return make_pair(a.r, a.s) > make_pair(b.r, b.s);
}

int st[200005],sz;
int n;

int main() {
    scanf("%d",&n);
    for(int i=0;i<n;++i) {
        point P;
	if(P.read(i)) V.push_back(P);
    }
    mX = *min_element(V.begin(),V.end(),cmpx);
    mY = *min_element(V.begin(),V.end(),cmpy);
    sort(V.begin(),V.end(),cmp);

    if(!(mX == mY)) {
	st[0]=0,st[1]=1,sz=2;
	n = V.size();
	for(int i=2;i<n;++i) {
	    if(V[st[sz-1]] == mX) break;
	    while(sz>=2 && ccw(V[st[sz-2]],V[st[sz-1]],V[i])>0) {
    	        sz--;
    	    } st[sz++]=i;
    	}
    }

    for(int i=0;i<sz;++i) {
    	for(auto x : idxs[make_pair(V[st[i]].s,V[st[i]].r)])
    		ans.push_back(x);
    }

    sort(ans.begin(), ans.end());
    for(int i=0;i<ans.size();++i) printf("%d ",ans[i]+1);
}


#include<cstdio>
#include<vector>
#include<queue>
#include<algorithm>
#include<cstring>
#include<cmath>
#include<map>

using namespace std;

map< pair<int,int>, vector<int> > idxs;

struct point {
    double x,y;
    int s,r;
    point() {}
    bool read(int i) {
    	int ss,rr; scanf("%d%d",&ss,&rr);
	s = ss, r = rr;
	x = 1.0 / s, y = 1.0 / r;
	bool ck = 1;
	if(idxs.count(make_pair(s,r))) ck = 0;
	idxs[make_pair(s,r)].push_back(i);
	return ck;
    }
    bool operator == (const point &rhs) const {
    	return s == rhs.s && r == rhs.r;
    }
};

double sqr(double x) {return x*x;}
const double eps = 1e-12;

int ccw(const point &p1, const point &p2, const point &p3) {
    double ret = (p2.x - p1.x)*(p3.y - p1.y) - (p2.y - p1.y)*(p3.x - p1.x);
    if(abs(ret) < eps) return 0;
    return ret > 0 ? 1 : -1;
}

vector<point> V;
vector<int> ans;
point mX,mY;

bool cmp(const point &a, const point &b) {
    int c=ccw(mY,a,b);
    if(c==0) return sqr(mY.x-a.x)+sqr(mY.y-a.y)<sqr(mY.x-b.x)+sqr(mY.y-b.y);
    return c<0;
}
bool cmpx(const point &a, const point &b) {
	return make_pair(a.s, a.r) > make_pair(b.s, b.r);
}
bool cmpy(const point &a, const point &b) {
	return make_pair(a.r, a.s) > make_pair(b.r, b.s);
}

int st[200005],sz;
int n;

int main() {
    scanf("%d",&n);
    for(int i=0;i<n;++i) {
        point P;
	if(P.read(i)) V.push_back(P);
    }
    mX = *min_element(V.begin(),V.end(),cmpx);
    mY = *min_element(V.begin(),V.end(),cmpy);
    sort(V.begin(),V.end(),cmp);

    st[0]=0,st[1]=1,sz=min((int)V.size(),2);
    n = V.size();
    for(int i=2;i<n;++i) {
        if(V[st[sz-1]] == mX) break;
	while(sz>=2 && ccw(V[st[sz-2]],V[st[sz-1]],V[i])>0) {
            sz--;
        } st[sz++]=i;
    }

    for(int i=0;i<sz;++i) {
    	for(auto x : idxs[make_pair(V[st[i]].s,V[st[i]].r)])
    		ans.push_back(x);
    }

    sort(ans.begin(), ans.end());
    for(int i=0;i<ans.size();++i) printf("%d ",ans[i]+1);
}