package main
import (
"bufio"
"fmt"
"os"
"sort"
)
type Segment struct {
id int
l int
r int
}
func main() {
reader := bufio.NewReader(os.Stdin)
var n int
if _, err := fmt.Fscan(reader, &n); err != nil {
return
}
segments := make([]Segment, n)
for i := 0; i < n; i++ {
segments[i].id = i
fmt.Fscan(reader, &segments[i].l, &segments[i].r)
}
adj := make([][]int, n)
for i := 0; i < n; i++ {
for j := i + 1; j < n; j++ {
if max(segments[i].l, segments[j].l) <= min(segments[i].r, segments[j].r) {
adj[i] = append(adj[i], j)
adj[j] = append(adj[j], i)
}
}
}
orderSegs := make([]Segment, n)
copy(orderSegs, segments)
sort.Slice(orderSegs, func(i, j int) bool {
if orderSegs[i].r != orderSegs[j].r {
return orderSegs[i].r < orderSegs[j].r
}
return orderSegs[i].l < orderSegs[j].l
})
order := make([]int, n)
for i := 0; i < n; i++ {
order[i] = orderSegs[i].id
}
ans := make([]int, n)
for i := 0; i < n; i++ {
ans[i] = i
}
if n == 1 {
fmt.Println(1)
return
}
limit := make([]int, n)
placed := make([]bool, n)
cnt := make([]int, n)
curAns := make([]int, n)
freq := make([]int, n)
check := func(M int) bool {
for i := 0; i < n; i++ {
limit[i] = n - 1
placed[i] = false
}
for i := 0; i < n; i++ {
for j := 0; j < n; j++ {
cnt[j] = 0
}
for j := 0; j < n; j++ {
if !placed[j] {
cnt[limit[j]]++
}
}
for x := 1; x < n; x++ {
cnt[x] += cnt[x-1]
}
if i > 0 && cnt[i-1] > 0 {
return false
}
reqX := n - 1
for x := i; x < n; x++ {
allowed := x - i + 1 - cnt[x]
if allowed == 0 {
if x < reqX {
reqX = x
}
} else if allowed < 0 {
return false
}
}
bestJ := -1
for _, j := range order {
if placed[j] {
continue
}
if limit[j] > reqX {
continue
}
possible := true
if i+M < n {
for x := 0; x < n; x++ {
freq[x] = 0
}
for _, k := range adj[j] {
if !placed[k] {
freq[limit[k]]++
}
}
c := 0
for x := n - 1; x >= i+M; x-- {
allowed := x - i + 1 - cnt[x]
if limit[j] <= x {
if c > allowed {
possible = false
break
}
} else {
if c > allowed-1 {
possible = false
break
}
}
c += freq[x]
}
}
if possible {
bestJ = j
break
}
}
if bestJ == -1 {
return false
}
placed[bestJ] = true
curAns[i] = bestJ
for _, k := range adj[bestJ] {
if !placed[k] && limit[k] > i+M {
limit[k] = i + M
}
}
}
return true
}
low := 1
high := n - 1
for low <= high {
mid := (low + high) / 2
if check(mid) {
copy(ans, curAns)
high = mid - 1
} else {
low = mid + 1
}
}
for i := 0; i < n; i++ {
if i > 0 {
fmt.Print(" ")
}
fmt.Print(ans[i] + 1)
}
fmt.Println()
}
func max(a, b int) int {
if a > b {
return a
}
return b
}
func min(a, b int) int {
if a < b {
return a
}
return b
}