module mod_priority_queue
  implicit none
  type t_priority_queue
    private
    integer :: num = 0
    integer, pointer :: heap(:) => null()
  contains
    procedure :: offer => offer
    procedure :: clear => clear
    procedure :: poll => poll
    procedure :: peek => peek
    procedure :: size => size_of
  end type
contains
  integer function compare(a,b)
    integer, intent(in) :: a, b
    compare = b-a
  end
  subroutine offer(this,item)
    class(t_priority_queue), intent(inout) :: this
    integer, intent(in) :: item
    integer :: n, i, t
    integer, allocatable :: tmp(:)
    if (.not.associated(this%heap)) allocate(this%heap(1))
    if (this%num == size(this%heap)) then
      allocate(tmp(this%num))
      tmp = this%heap
      deallocate(this%heap)
      allocate(this%heap(2*this%num))
      this%heap(1:this%num) = tmp
      deallocate(tmp)
    end if
    this%num = this%num+1
    this%heap(this%num) = item
    n = this%num
    do while (n > 1)
      i = n/2
      if (compare(this%heap(n),this%heap(i)) < 0) then
        t = this%heap(n)
        this%heap(n) = this%heap(i)
        this%heap(i) = t
      end if
      n = i
    end do
  end
  subroutine clear(this)
    class(t_priority_queue), intent(inout) :: this
    if (associated(this%heap)) deallocate(this%heap)
    this%num = 0
  end
  function poll(this) result(item)
    class(t_priority_queue), intent(inout) :: this
    integer :: item, n, i, j, tmp
    n = this%num
    item = this%heap(1)
    this%heap(1) = this%heap(n)
    this%num = this%num-1
    i = 1
    do while (2*i < n)
      j = 2*i
      if (j+1 < n .and. compare(this%heap(j+1),this%heap(j)) < 0) j = j+1
      if (compare(this%heap(j),this%heap(i)) < 0) then
        tmp = this%heap(j)
        this%heap(j) = this%heap(i)
        this%heap(i) = tmp
      end if
      i = j
    end do
  end
  function peek(this) result(item)
    class(t_priority_queue), intent(in) :: this
    integer :: item
    item = this%heap(1)
  end
  integer function size_of(this)
    class(t_priority_queue), intent(in) :: this
    size_of = this%num
  end
end module mod_priority_queue
module mod_array_list
  implicit none
  type t_array_list
    private
    integer :: num = 0
    integer, pointer :: arr(:) => null()
  contains
    procedure :: add => add
    procedure :: clear => clear
    procedure :: get => get
    procedure :: remove => remove
    procedure :: replace => replace
    procedure :: first_index_of => first_index_of
    procedure :: last_index_of => last_index_of
    procedure :: size => size_of
  end type
contains
  subroutine add(this,item)
    class(t_array_list), intent(inout) :: this
    integer, intent(in) :: item
    integer, allocatable :: tmp(:)
    if (.not.associated(this%arr)) allocate(this%arr(1))
    if (this%num == size(this%arr)) then
      allocate(tmp(this%num))
      tmp = this%arr
      deallocate(this%arr)
      allocate(this%arr(2*this%num))
      this%arr(1:this%num) = tmp
      deallocate(tmp)
    end if
    this%num = this%num+1
    this%arr(this%num) = item
  end
  subroutine clear(this)
    class(t_array_list), intent(inout) :: this
    if (associated(this%arr)) deallocate(this%arr)
    this%num = 0
  end
  function get(this,i) result(item)
    class(t_array_list), intent(in) :: this
    integer, intent(in) :: i
    integer :: item
    item = this%arr(i)
  end
  function remove(this,i) result(item)
    class(t_array_list), intent(inout) :: this
    integer, intent(in) :: i
    integer :: item
    item = this%arr(i)
    this%arr(i:) = this%arr(i+1:)
    this%num = this%num-1
  end
  subroutine replace(this,i,item)
    class(t_array_list), intent(inout) :: this
    integer, intent(in) :: i
    integer :: item
    this%arr(i) = item
  end
  function first_index_of(this,item) result(idx)
    class(t_array_list), intent(in) :: this
    integer, intent(in) :: item
    integer :: idx, i
    idx = -1
    do i = 1, this%num
      if (this%arr(i) == item) then
        idx = i
        return
      end if
    end do
  end
  function last_index_of(this,item) result(idx)
    class(t_array_list), intent(in) :: this
    integer, intent(in) :: item
    integer :: idx, i
    idx = -1
    do i = this%num, 1, -1
      if (this%arr(i) == item) then
        idx = i
        return
      end if
    end do
  end
  integer function size_of(this)
    class(t_array_list), intent(in) :: this
    size_of = this%num
  end
end module mod_array_list
program exhausted
  use mod_priority_queue
  use mod_array_list
  implicit none
  integer :: n, m, l, r, i, j, t = 0, ans
  type(t_priority_queue) :: pq
  type(t_array_list), allocatable, dimension(:) :: list
  read(*,*) n, m
  allocate(list(0:m))
  do i = 1, n
    read(*,*) l, r
    call list(l)%add(r)
  end do
  do i = m, 0, -1
    do j = 1, list(i)%size()
      call pq%offer(list(i)%get(j))
    end do
    if (i > 0 .and. pq%size() > 0) then
      l = pq%poll()
      t = t+1
    end if
  end do
  ans = n-t
  r = m
  do while (pq%size() > 0)
    l = pq%poll()
    if (l <= r .and. r > t) then
      ans = ans-1
      r = r-1
    end if
  end do
  write(*,'(i0)') ans
end program exhausted

Measured memory_bytes: 15072