CodeEff/ECCO huggingface dataset:
# Original solution
import sys
sys.setrecursionlimit(2147483647)
INF=float("inf")
MOD=10**9+7
input=lambda :sys.stdin.readline().rstrip()
def resolve():
    from collections import Counter
    n=int(eval(input()))
    A=list(Counter(list(map(int,input().split()))).values())
    A.sort()
    m=len(A)
    S=[0]*(m+1) # cumulative distribution
    for i in range(m): S[i+1]=S[i]+A[i]
    # output
    p=n
    i=m
    from bisect import bisect_left
    for k in range(1,n+1):
        while(1):
            # pに対して先にi_pを求めておく
            while(1):
                if(i<=0 or A[i-1]<p): break
                i-=1
            if(S[i]+p*(m-i)>=k*p): break # p<0 or を書く必要はない
            p-=1 # pの条件が真になるまで減らし続ける
        print(p)
resolve()

# Optimized solution
import sys
sys.setrecursionlimit(2147483647)
INF=float("inf")
MOD=10**9+7
input=lambda :sys.stdin.readline().rstrip()
def bin_sort(A,n_min=None,n_max=None):
    if(n_min is None): n_min=min(A)
    if(n_max is None): n_max=max(A)
    bin=[0]*(n_max-n_min+1)
    for a in A: bin[a-n_min]+=1
    B=[]
    for i in range(n_min,n_max+1): B+=[i]*bin[i-n_min]
    return B

def resolve():
    n=int(eval(input()))
    A=[0]*n
    for a in map(int,input().split()): A[a-1]+=1
    A=bin_sort(A,0,n)
    S=[0]*(n+1)
    for i in range(n): S[i+1]=S[i]+A[i]
    # output
    p=n; i=n
    for k in range(1,n+1):
        while(1):
            while(1):
                if(i<=0 or A[i-1]<p): break
                i-=1
            if(S[i]+p*(n-i)>=k*p): break
            p-=1
        print(p)
resolve()
# Original solution
import collections
import bisect
n=int(eval(input()))
a=collections.Counter(list(map(int,input().split())))
a=list(a.values())
a.sort()
b=[0]*len(a)
b[0]=a[0]
for i in range(len(a)-1):
    b[i+1]=b[i]+a[i+1]
s=sum(a)
#print(a,b)
ans=[i for i in range(0,n+1)]
ans=ans[::-1]
for t in range(1,n+1):
    ANS=ans[n+(-n//t):]
    #print(ANS)
    for A in ANS:
        z=bisect.bisect_right(a,A)
        #print(z)
        if A*t<=(b[z-1] if z>=1 else 0)+A*(len(b)-z):
            print(A)
            break

# Optimized solution
import collections
import bisect
n=int(eval(input()))
a=collections.Counter(list(map(int,input().split())))
a=list(a.values())
a.sort()
b=[0]*len(a)
b[0]=a[0]
for i in range(len(a)-1):
    b[i+1]=b[i]+a[i+1]
s=sum(a)
ans=[i for i in range(0,n+1)]
ans=ans[::-1]
for t in range(1,n+1):
    ANS=ans[n+(-n//t):]
    for A in ANS:
        z=bisect.bisect_right(a,A)
        if A*t<=(b[z-1] if z>=1 else 0)+A*(len(b)-z):
            print(A)
            break
# Original solution
from collections import Counter
from copy import deepcopy

n = int(eval(input()))
a = list(map(int, input().split()))
c = Counter(a)

for k in range(1, n + 1):
    cx = deepcopy(c)

    count = 0

    while k <= len(cx):
        # print(cx)
        mc = cx.most_common()
        for key, _ in mc[:k]:
            cx[key] -= 1
            if cx[key] < 1:
                del cx[key]
        count += 1

    print(count)


# Optimized solution
from collections import Counter
from itertools import accumulate

# from copy import deepcopy

n = int(eval(input()))
a = list(map(int, input().split()))
c = Counter(a)

# for k in range(1, n + 1):
#     cx = deepcopy(c)

#     count = 0

#     while k <= len(cx):
#         # print(cx)
#         mc = cx.most_common()
#         for key, _ in mc[:k]:
#             cx[key] -= 1
#             if cx[key] < 1:
#                 del cx[key]
#         count += 1

#     print(count)

cv = Counter(list(c.values()))
max_take = max(cv.keys())

lx = list(accumulate(cv[i] for i in range(max_take + 1)))
rx = list(accumulate(cv[i] * i for i in range(max_take + 1)))
ax = [rx[i] + (lx[-1] - lx[i]) * i for i in range(max_take + 1)]


def bisec(l0, r0, predicate):
    l, r = l0, r0

    while abs(l - r) > 1:
        mid = (l + r) // 2
        if predicate(mid):
            r = mid
        else:
            l = mid

    return r


for k in range(1, n + 1):
    print((bisec(n + 1, 0, lambda x: x * k <= ax[min(x, max_take)])))
# Original solution
import bisect

n = int(eval(input()))
k = sorted(map(int, input().split()))

hist = []
count = 0
for i in range(n):
    count += 1
    if i == n - 1 or k[i] != k[i + 1]:
        hist.append(count)
        count = 0
hist.sort()

sumh = [0]
for i in range(len(hist)):
    sumh.append(sumh[-1] + hist[i])

def ok(h, d):
    i = bisect.bisect_left(hist, h)
    s = sumh[i] + h * (len(hist) - i)
    return s >= h * d

def binary_search(d):
    lo, hi = 0, 10 ** 10
    while hi - lo > 1:
        mid = (lo + hi) // 2
        if ok(mid, d):
            lo = mid
        else:
            hi = mid
    return lo

for d in range(1, n + 1):
    print((binary_search(d)))


# Optimized solution
import bisect

n = int(eval(input()))
k = sorted(map(int, input().split()))

hist = []
count = 0
for i in range(n):
    count += 1
    if i == n - 1 or k[i] != k[i + 1]:
        hist.append(count)
        count = 0
hist.sort()

sumh = [0]
for i in range(len(hist)):
    sumh.append(sumh[-1] + hist[i])

def ok(h, d):
    i = bisect.bisect_left(hist, h)
    s = sumh[i] + h * (len(hist) - i)
    return s >= h * d

def binary_search(d):
    lo, hi = 0, n // d + 1
    while hi - lo > 1:
        mid = (lo + hi) // 2
        if ok(mid, d):
            lo = mid
        else:
            hi = mid
    return lo

for d in range(1, n + 1):
    print((binary_search(d)))
# Original solution
import sys
input = sys.stdin.readline

from collections import Counter
from copy import deepcopy
from heapq import heapify, heappush, heappop


def main():
    n = int(eval(input()))
    a = list(map(int, input().split()))

    #n = 3 * 10 ** 5
    #a = list(range(1, n + 1))

    c = Counter(a)
    c = list(c.values())
    heapify(c)

    k_mx = len(c)

    for k in range(1, n + 1):
        if k > k_mx:
            print((0))
            continue

        cp = deepcopy(c)

        for _ in range(k_mx - k):
            cnt = heappop(cp)
            while cnt:
                mn = heappop(cp)
                cnt -= 1
                heappush(cp, mn + 1)

        ans = heappop(cp)
        print(ans)


if __name__ == "__main__":
    main()


# Optimized solution
import sys
input = sys.stdin.readline

from collections import Counter
from itertools import accumulate
from math import floor
from bisect import bisect_left


def main():
    n = int(eval(input()))
    a = list(map(int, input().split()))

    c = Counter(a)
    c = list(c.values())

    d = Counter(c)
    d_li = [0] * (n + 1)
    for k, v in list(d.items()):
        d_li[k] = v

    dk_acm = list(accumulate(d_li))

    kdk_acm = [0]
    for k, e in enumerate(d_li[1:], 1):
        kdk_acm.append(kdk_acm[-1] + k * e)

    def f(x):
        kdk_sm = kdk_acm[x]
        dk_sm = dk_acm[n] - dk_acm[x]

        return floor((kdk_sm + x * dk_sm) / x)

    fs = [float("inf")] + [f(x) for x in range(1, n + 1)]
    fs = fs[::-1]

    for k in range(1, n + 1):
        print((n - bisect_left(fs, k)))


if __name__ == "__main__":
    main()
# Original solution
N = int(eval(input()))
A = list(map(int, input().split()))

C = [0] * N
D = [0] * (N + 1)
for a in A:
    C[a-1] += 1
    D[C[a-1]] += 1

S = [0] * (N + 1)
for i in range(N):
    S[i+1] = S[i] + D[i+1]

for K in range(1,N+1):
    l = 0
    r = N + 1
    while(r-l>1):
        m = int((l+r)/2)
        if S[m] >= K * m:
            l = m
        else:
            r = m
    print(l)

# Optimized solution
N = int(eval(input()))
A = list(map(int, input().split()))

C = [0] * N
D = [0] * (N + 1)
for a in A:
    C[a - 1] += 1
    D[C[a - 1]] += 1

S = [0] * (N + 1)
for i in range(N):
    S[i + 1] = S[i] + D[i + 1]

ans = N
for K in range(1, N + 1):
    while ans > 0 and S[ans] < K * ans:
        ans -= 1
    print(ans)
# Original solution
I = int(eval(input()))
from collections import Counter
from itertools import accumulate
As = list(map(int, input().split()))
xs = sorted([x for x in list(Counter(As).values())]) + [10**18]
Xs = accumulate(xs)

def bsearch(target, min_i, max_i, func):
    # func(index) <= target < func(index+1) となるindexを返す
    if func(max_i) <= target:
        return max_i
    if target < func(min_i):
        return min_i - 1
    index = (max_i + min_i)//2
    while True:
        if func(index) <= target:
            if target < func(index+1):
                return index
            index, min_i = (index+1 + max_i)//2, index+1
            continue
        index, max_i = (index-1 + min_i)//2, index-1

#for x in xs:
N = len(xs) - 1
rs = [0]*I
mny = N+1
for l, (x, X) in enumerate(zip(xs[1:], Xs)):
    l += 2
    y = bsearch(0, N-l+2, N+1, lambda k: x > X//(k-(N-l+1)))
    y+=1
    #print(l, y, X//(y-(N-l+1)))
    for i in range(y, mny):
        rs[i-1] = X//(i-(N-l+1))
    mny = min(y, mny)
for r in rs:
    print(r)

# Optimized solution
I = int(eval(input()))
from collections import Counter
from itertools import accumulate
As = list(map(int, input().split()))
xs = sorted([x for x in list(Counter(As).values())]) + [10**18]
Xs = accumulate(xs)

N = len(xs) - 1
rs = [0]*I
mny = N+1
for l, (x, X) in enumerate(zip(xs[1:], Xs)):
    l += 2
    y = X//(x+1) + (N-l+1) + 1
    if y-(N-l+1) > 0 and x <= X//(y-(N-l+1)):
        y+=1
    for i in range(y, mny):
        rs[i-1] = X//(i-(N-l+1))
    mny = min(y, mny)
for r in rs:
    print(r)
# Original solution
I = int(eval(input()))
from collections import Counter
from itertools import accumulate
As = list(map(int, input().split()))
xs = sorted([x for x in list(Counter(As).values())]) + [10**18]
Xs = accumulate(xs)

N = len(xs) - 1
rs = [0]*I
mny = N+1
for l, (x, X) in enumerate(zip(xs[1:], Xs)):
    l += 2
    y = X//(x+1) + (N-l+1) + 1
    if y-(N-l+1) > 0 and x <= X//(y-(N-l+1)):
        y+=1
    for i in range(y, mny):
        rs[i-1] = X//(i-(N-l+1))
    mny = min(y, mny)
for r in rs:
    print(r)

# Optimized solution
I = int(eval(input()))
from collections import Counter
from itertools import accumulate
As = list(map(int, input().split()))
xs = sorted([x for x in list(Counter(As).values())]) + [10**18]
Xs = accumulate(xs)

N = len(xs) - 1
rs = [0]*I
mny = N+1
for l, (x, X) in enumerate(zip(xs[1:], Xs)):
    l += 2
    y = X//(x+1) + (N-l+1) + 1
    for i in range(y, mny):
        rs[i-1] = X//(i-(N-l+1))
    mny = min(y, mny)
for r in rs:
    print(r)
# Original solution
import sys 
import collections as cl

N=int(eval(input()))
A=list(map(int,sys.stdin.readline().split()))
c=cl.Counter(A)
NumberTupleList=c.most_common()
NumberList=[x[1] for x in NumberTupleList[::-1]]
LengthOfNumberList=len(NumberList)
FormulaList=[sum([min(NumberList[i],x) for i in range(LengthOfNumberList)])/x for x in range(1,N+1)]

pin=N-1
for K in range(1,N+1):
    while pin>=0 and K>FormulaList[pin]:
        pin-=1
    print((pin+1))


# Optimized solution
import sys 
import collections as cl


N=int(eval(input()))
A=list(map(int,sys.stdin.readline().split()))
c=cl.Counter(A)
NumberTupleList=c.most_common()
NumberList=[x[1] for x in NumberTupleList[::-1]]
LengthOfNumberList=len(NumberList)
FormulaList=[0 for i in range(N)]
flag=0
S=sum(NumberList)
for x in range(1,N+1):
    while flag<LengthOfNumberList and NumberList[flag]<=x:
        flag+=1
    if flag<LengthOfNumberList:
        FormulaList[x-1]=(sum(NumberList[:flag])+x*(LengthOfNumberList-flag))/x
    else:
        FormulaList[x-1]=S/x
pin=N-1
for K in range(1,N+1):
    while pin>=0 and K>FormulaList[pin]:
        pin-=1
    print((pin+1))
# Original solution
import sys
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines
read = sys.stdin.buffer.read
sys.setrecursionlimit(10 ** 7)
INF = float('inf')

N = int(eval(input()))

import collections
d = collections.defaultdict(list)

for i in range(N):
    S, P = input().split()
    P = int(P)
    d[S].append((i+1, P))

ordered = list(d.keys())
ordered.sort()

for city in ordered:
    mises = d[city]
    mises = sorted(mises, key=lambda x: x[1], reverse=True)
    for mise in mises:
        print((mise[0]))

# Optimized solution
import sys
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines
read = sys.stdin.buffer.read
sys.setrecursionlimit(10 ** 7)
INF = float('inf')

N = int(eval(input()))
 
SP = []
for i in range(N):
  s,p = input().split()
  SP.append((s,-int(p),i+1))
  
SP.sort()
 
for s,p,i in SP:
  print(i)
# Original solution
N = int(eval(input()))
Book = [0] * N
for i in range(N):
    s,q = input().split()
    p = int(q)
    Book[i] = (s, 100-p, i)

Book.sort()

for i in range(N):
    print((Book[i][2]+1))




# Optimized solution
N = int(eval(input()))
L = []
for _ in range(N):
    s, p = input().split()
    p = int(p)
    L.append((s, 100 - p, _))

L.sort()
for _ in range(N):
    print((L[_][2]+1))
# Original solution
N = int(eval(input()))
S = [None]*N
P = [None]*N
I = [None]*N
for i in range(N):
    tmp = input().split()
    S[i] = tmp[0]
    P[i] = int(tmp[1])
    I[i] = i+1


def less(a, b):
    if a[0] == b[0]:
        if a[1] == b[1]:
            return a[2] < b[2]
        return a[1] > b[1]
    return a[0] < b[0]


for i in range(N):
    for j in range(i+1, N):
        if not less([S[i], P[i], I[i]], [S[j], P[j], I[j]]):
            S[i], S[j] = S[j], S[i]
            P[i], P[j] = P[j], P[i]
            I[i], I[j] = I[j], I[i]

for i in range(N):
    print((I[i]))


# Optimized solution
N = int(eval(input()))
T = [None]*N
for i in range(N):
    tmp = input().split()
    T[i] = (tmp[0], -int(tmp[1]), i+1)

T.sort()
for t in T:
    print((t[2]))
# Original solution
import operator as op

n = int(eval(input()))
s = []
for i in range(n):
  a , b  = input().split()
  s.append((a,int(b),i+1))

s1 = sorted(s,key = op.itemgetter(1),reverse=True)
s2 = sorted(s1,key = op.itemgetter(0))
for i in range(n):
  print((s2[i][2]))

# Optimized solution
n = int(eval(input()))
s = []
for i in range(n):
  a , b  = input().split()
  s.append((a,int(b),i+1))

s1 = sorted(s,key = lambda S:S[1],reverse=True)
s2 = sorted(s1,key = lambda S:S[0])
for i in range(n):
  print((s2[i][2]))
# Original solution
n = int(eval(input()))
dat = []
for i in range(n):
    s,p = input().split()
    p = int(p)
    dat.append((s, p, i+1))
res = sorted(dat, key=lambda x: (x[0], -x[1]))
for i in range(len(res)):
    print((res[i][2]))

# Optimized solution
n = int(eval(input()))
dat = []
for i in range(n):
    s,p = input().split()
    dat.append((s, int(p), i+1))
res = sorted(dat, key=lambda x: (x[0], -x[1]))
for i in range(len(res)):
    print((res[i][2]))
# Original solution
n=int(eval(input()))
l={}
for i in range(n):
  s,p=input().split()
  p=int(p)
  if s in l:
    l[s].append([p,i+1])
  else:
    l[s]=[[p,i+1]]

dk=sorted(l.keys())
for i in dk:
  l[i].sort(reverse=True, key=lambda x:x[0])
  for j,k in l[i]:
    print(k)

# Optimized solution
n=int(eval(input()))
l=[]
for i in range(n):
  s,p=input().split()
  p=int(p)*-1
  l.append([s,p,i+1])
l.sort()

for i in l:
  print((i[2]))
# Original solution
n = int(eval(input()))
S = []
count = [0] * n
for i in range(n):
    a, b = input().split()
    S.append([a, -int(b), i + 1])

S.sort()

for i in range(n):
    print((S[i][2]))



# Optimized solution
n = int(eval(input()))
S = []
count = [0] * n
for i in range(n):
    a, b = input().split()
    S.append([a, -int(b), i + 1])

S.sort(key=lambda x:(x[0], x[1]))

for i in range(n):
    print((S[i][2]))
# Original solution
n=int(eval(input()))
c,m=[],[]
d={}
t={}
for i in range(n):
    s,p=list(map(str,input().split()))
    m.append((s,int(p)))
    if s not in c:
        c.append(s)
        d[s]=[int(p)]
    else:
        d[s].append(int(p))
    t[(s,int(p))]=i+1
c.sort()
ans={}
cnt=1
for i in c:
    d[i].sort(reverse=True)
    for j in d[i]:
        ans[cnt]=(i,j)
        cnt+=1
for i in range(1,n+1):
    print((t[ans[i]]))


# Optimized solution
n=int(eval(input()))
ans=[]
for i in range(n):
    s,p=list(map(str,input().split()))
    ans.append((s,int(p)*-1,i+1))
ans.sort()
for i in ans: print((i[2]))
# Original solution
n = int(eval(input()))
lt = []
for i in range(n):
  s, p = input().split()
  lt.append((s, -int(p)))

lts = sorted(lt)

for t in lts:
  print((lt.index(t)+1))

# Optimized solution
ll=[]
for i in range(int(eval(input()))):
  s,p=input().split()
  ll.append([s,-int(p),i+1])
for l in sorted(ll):
  print((l[2]))
# Original solution
n = int(input())
s_p = []
for i in range(n):
    s,p = input().split()
    s_p.append([s,-int(p),i+1])
s_p.sort(key=lambda x:(x[0],x[1]))
[print(s_p[i][2]) for i in range(n)]


# Optimized solution
n = int(eval(input()))
r = []
for i in range(n):
    s,p = input().split()
    r.append([s,-int(p),i+1])
r.sort(key=lambda x:(x[0],x[1]))
for i in r:
    print((i[2]))
# Original solution
n = int(eval(input()))
d = {}
for i in range(n):
    s ,p = input().split()
    p = int(p)
    if not(s in d):
        d[s] = {}
    d[s][p*-1] = i+1
for i in sorted(d.keys()):
    for j in sorted(d[i].keys()):
        print((d[i][j]))


# Optimized solution
n = int(eval(input()))
s = []
p = [0] * 101
d = {}
for i in range(n):
    a,b = input().split()
    b = int(b)
    s.append(a)
    p[b] = i+1
    if a in list(d.keys()):
        d[a].append(b)
        continue
    d[a] = [b]
s = sorted(set(s))
for i in s:
    c = sorted(d[i],reverse=True)
    for j in c:
        print((p[j]))
# Original solution

# import numpy as np
# import numpypy as np
import sys
input = sys.stdin.readline

def eprint(*args, **kwargs):
    print(*args, file=sys.stderr, **kwargs)

import math
import string
import fractions
import re
import array
import copy
import functools
import operator

import collections
import itertools
import bisect
import heapq


from heapq import heappush
from heapq import heappop

# from itertools import accumulate
# from collections import deque
import random


def main():
    n = int(eval(input()))
    dict={}
    for i in range(n):
        name, score= input().split()
        if not(name in dict):
            dict[name]=[((int(score),i+1))]
        else:
            dict[name].append((int(score),i+1))
            dict[name].sort(reverse=True)
    eprint(dict)
    ll=list(dict.items())
    eprint(ll)
    ll.sort()
    eprint(ll)
    for x in ll:
        for y in x[1]:
            print(y[1])
        
if __name__ == '__main__':
    main()


# Optimized solution

# import numpy as np
# import numpypy as np
import sys
input = sys.stdin.readline

def eprint(*args, **kwargs):
    print(*args, file=sys.stderr, **kwargs)

# import math
# import string
# import fractions
# from fractions import Fraction
# from fractions import gcd
# def lcm(n,m):
#     return int(n*m/gcd(n,m))

# import re
# # import array
# import copy
# import functools
# import operator

# import collections
# import itertools
# import bisect
# import heapq


# from heapq import heappush
# from heapq import heappop

# # from itertools import accumulate
# # from collections import deque
# import random

from queue import PriorityQueue as pq
# class ReversePriorityQueue(PriorityQueue):
#     def __cmp__(self, other):
#         return -cmp(self.degree, other.degree)
#     # def put(self, tup):
    #     newtup = tup[0] * -1, tup[1]
    #     PriorityQueue.put(self, newtup)

    # def get(self):
    #     tup = PriorityQueue.get(self)
    #     newtup = tup[0] * -1, tup[1]
    #     return newtup

def main():
    n = int(eval(input()))
    dict={}
    for i in range(1,n+1):
        str_x,num = input().split()
        num =int(num)
        if (str_x in dict):
            dict[str_x].put((-num,i))
            # dict[str_x].sort(key = lambda x : x[1])
        else:
            a=pq()
            dict[str_x]=a
            dict[str_x].put((-num,i))
            # a.put([num,i])
    eprint(dict)
    ll = sorted(list(dict.items()))
    eprint(ll)
    # for i in ll:
    #     for j in i[1]:
    #         print(j[1])
    for item in ll:
        while item[1].qsize():
            print((item[1].get())[1])
if __name__ == '__main__':
    main()
# Original solution

# import numpy as np
# import numpypy as np
import sys
input = sys.stdin.readline

def eprint(*args, **kwargs):
    print(*args, file=sys.stderr, **kwargs)

# import math
# import string
# import fractions
# from fractions import Fraction
# from fractions import gcd
# def lcm(n,m):
#     return int(n*m/gcd(n,m))

# import re
# import array
# import copy
# import functools
# import operator

# import collections
# import itertools
# import bisect
# import heapq


# from heapq import heappush
# from heapq import heappop
# from queue import PriorityQueue as pq

# # from itertools import accumulate
# # from collections import deque
# import random


def main():
    n = int(eval(input()))
    l=[["",0,0] for i in range(n)]
    # eprint(l)
    for i in range(n):
        s,m=input().split()
        m=-int(m)
        l[i][0]=s
        l[i][1]=m
        l[i][2]=i+1
    # eprint(l)
    l.sort()
    # eprint(l)
    for x in l:
        print(x[2])

if __name__ == '__main__':
    main()


# Optimized solution

# import numpy as np
# import numpypy as np
import sys
input = sys.stdin.readline

def eprint(*args, **kwargs):
    print(*args, file=sys.stderr, **kwargs)

# import math
# import string
# import fractions
# from fractions import Fraction
# from fractions import gcd
# def lcm(n,m):
#     return int(n*m/gcd(n,m))

# import re
# import array
# import copy
# import functools
# import operator

# import collections
# import itertools
# import bisect
# import heapq


# from heapq import heappush
# from heapq import heappop
# from queue import PriorityQueue as pq

# # from itertools import accumulate
# # from collections import deque
# import random


def main():
    n = int(eval(input()))
    # l=[["",0,0] for i in range(n)]
    l=[]
    # eprint(l)
    for i in range(n):
        s,m=input().split()
        m = -int(m)
        l.append([s,m,i+1])
        # l[i][0]=s
        # l[i][1]=m
        # l[i][2]=i+1
    # eprint(l)
    l.sort()
    # eprint(l)
    for x in l:
        print(x[2])

if __name__ == '__main__':
    main()
# Original solution
n = int(eval(input()))
X = []
for i in range(n):
    s, p = list(map(str, input().split()))
    p = int(p)
    X.append((s, p, i+1))

X.sort(key= lambda x: (x[0], -x[1]))
for s, p, i in X:
    print(i)


# Optimized solution
n = int(eval(input()))
SP = []
for i in range(n):
    s, p = list(map(str, input().split()))
    p = int(p)
    SP.append((s, p, i+1))
SP.sort(key=lambda x: (x[0], -x[1]))
for s, p, j in SP:
    print(j)
# Original solution
#!/usr/bin/env python3
#ABC128 B

import sys
import math
import bisect
from heapq import heappush, heappop
from collections import defaultdict
from itertools import accumulate
from collections import Counter
from collections import deque
from operator import itemgetter
mod = 10**9 + 7

n = int(eval(input()))
sp = [list(input().split()) for _ in range(n)]
for i in range(n):
    sp[i].append(i+1)
sp.sort(key = lambda x:(x[0],-int(x[1])))
for i in range(n):
    print((sp[i][2]))
    


# Optimized solution
#!/usr/bin/env python3
#ABC128 B

import sys
import math
from bisect import bisect_right as br
from bisect import bisect_left as bl
sys.setrecursionlimit(1000000)
from heapq import heappush, heappop,heappushpop
from collections import defaultdict
from itertools import accumulate
from collections import Counter
from collections import deque
from operator import itemgetter
from itertools import permutations
mod = 10**9 + 7
inf = float('inf')
def I(): return int(sys.stdin.readline())
def LI(): return list(map(int,sys.stdin.readline().split()))

n = I()
lst = []
for i in range(n):
    s,p = input().split()
    lst.append((s,int(p),i+1))
lst.sort(key = lambda x:(x[0],-x[1]))
for i,j,k in lst:
    print(k)
# Original solution
N=int(eval(input()))
rest_list = []
for i in range(N):
  Si, Pi = input().split()
  Pi = int(Pi)
  rest_list.append((i+1,Si,Pi))
  
for i in range(N-1):
  for j in range(i+1,N):
    ii,Si,Pi = rest_list[i]
    jj,Sj,Pj = rest_list[j]
    
    if Si > Sj or (Si == Sj and Pi < Pj):
      rest_list[i], rest_list[j] = (jj,Sj,Pj),(ii,Si,Pi)
      
for i in range(N):
  i,Si,Pi = rest_list[i]  
  print(i)
      

# Optimized solution
N=int(eval(input()))
rest_list=[]
for i in range(N):
  S,P=input().split()
  rest_list.append((S,-int(P),i+1))
rest_list.sort()

for s,p,i in rest_list:
  print(i)