module mod_t_item
  implicit none
  type :: t_item
    integer :: n
  end type t_item
  private
  public :: t_item, itemize, compare, swap
contains
  function itemize(n) result(i)
    implicit none
    integer :: n
    type(t_item) :: i
    i%n = n
    return
  end function itemize
  function compare(i1,i2) result(c)
    implicit none
    type(t_item), intent(in) :: i1, i2
    integer :: c
    c = i1%n-i2%n
    return
  end function compare
  subroutine swap(i1,i2)
    implicit none
    type(t_item), intent(inout) :: i1, i2
    type(t_item) :: i
    i = i1
    i1 = i2
    i2 = i
    return
  end subroutine swap
end module mod_t_item
module mod_t_list
  use mod_t_item
  implicit none
  type :: t_list
    integer :: vol
    type(t_item), pointer :: arr(:)
  end type t_list
  private
  public :: t_list, init_list, release_list, push_back
  public :: pop_back, poll_back, get_at, size_of_list
contains
  subroutine init_list(list)
    implicit none
    type(t_list), intent(inout) :: list
    list%vol = 0
    nullify(list%arr)
    allocate(list%arr(1))
    return
  end subroutine init_list
  subroutine release_list(list)
    implicit none
    type(t_list), intent(inout) :: list
    if (associated(list%arr)) deallocate(list%arr)
    return
  end subroutine release_list
  subroutine push_back(list,item)
    implicit none
    type(t_list), intent(inout) :: list
    type(t_item), intent(in) :: item
    type(t_item), allocatable :: tmp(:)
    if (size(list%arr).eq.list%vol) then
      allocate(tmp(list%vol))
      tmp = list%arr
      deallocate(list%arr)
      allocate(list%arr(2*list%vol))
      list%arr(1:list%vol) = tmp
      deallocate(tmp)
    end if
    list%vol = list%vol+1
    list%arr(list%vol) = item
    return
  end subroutine push_back
  function pop_back(list) result(item)
    implicit none
    type(t_list), intent(inout) :: list
    type(t_item) :: item
    item = list%arr(list%vol)
    list%vol = list%vol-1
    return
  end function pop_back
  subroutine poll_back(list)
    implicit none
    type(t_list), intent(inout) :: list
    list%vol = list%vol-1
    return
  end subroutine poll_back
  function get_at(list,i) result(item)
    implicit none
    type(t_list), intent(in) :: list
    integer, intent(in) :: i
    type(t_item) :: item
    item = list%arr(i)
    return
  end function get_at
  function size_of_list(list) result(s)
    implicit none
    type(t_list), intent(in) :: list
    integer :: s
    s = list%vol
    return
  end function size_of_list
end module mod_t_list
module mod_t_priority_queue
  use mod_t_item
  use mod_t_list
  implicit none
  type :: t_heap
    type(t_list) :: list
  end type t_heap
  private
  public :: t_heap, init_heap, release_heap, size_of_heap
  public :: peek, push, pop, poll
contains
  subroutine init_heap(heap)
    implicit none
    type(t_heap), intent(inout) :: heap
    call init_list(heap%list)
    return
  end subroutine init_heap
  subroutine release_heap(heap)
    implicit none
    type(t_heap), intent(inout) :: heap
    call release_list(heap%list)
    return
  end subroutine release_heap
  function size_of_heap(heap) result(s)
    implicit none
    type(t_heap), intent(in) :: heap
    integer :: s
    s = size_of_list(heap%list)
    return
  end function size_of_heap
  subroutine push_item(heap,item)
    implicit none
    type(t_heap), intent(inout) :: heap
    type(t_item), intent(in) :: item
    integer :: n, i
    call push_back(heap%list,item)
    n = heap%list%vol
    do while (n.gt.1)
      i = n/2
      if (compare(heap%list%arr(n),heap%list%arr(i)).lt.0) then
        call swap(heap%list%arr(n),heap%list%arr(i))
      end if
      n = i
    end do
    return
  end subroutine push_item
  function pop_item(heap) result(item)
    implicit none
    type(t_heap), intent(inout) :: heap
    type(t_item) :: item, tmp
    integer :: n, i, j
    n = heap%list%vol
    item = heap%list%arr(1)
    heap%list%arr(1) = heap%list%arr(n)
    tmp = pop_back(heap%list)
    i = 1
    do while (2*i.lt.n)
      j = 2*i
      if ((j.lt.n-1).and.(compare(heap%list%arr(j+1),heap%list%arr(j)).lt.0)) then
        j = j+1
      end if
      if (compare(heap%list%arr(j),heap%list%arr(i)).lt.0) then
        call swap(heap%list%arr(j),heap%list%arr(i))
      end if
      i = j
    end do
    return
  end function pop_item
  subroutine poll_item(heap)
    implicit none
    type(t_heap), intent(inout) :: heap
    type(t_item) :: item, tmp
    integer :: n, i, j
    n = heap%list%vol
    heap%list%arr(1) = heap%list%arr(n)
    call poll_back(heap%list)
    i = 1
    do while (2*i.lt.n)
      j = 2*i
      if ((j.lt.n-1).and.(compare(heap%list%arr(j+1),heap%list%arr(j)).lt.0)) then
        j = j+1
      end if
      if (compare(heap%list%arr(j),heap%list%arr(i)).lt.0) then
        call swap(heap%list%arr(j),heap%list%arr(i))
      end if
      i = j
    end do
    return
  end subroutine poll_item
  function peek_item(heap) result(item)
    implicit none
    type(t_heap), intent(inout) :: heap
    type(t_item) :: item
    item = heap%list%arr(1)
    return
  end function peek_item
  subroutine push(heap,n)
    implicit none
    type(t_heap), intent(inout) :: heap
    integer :: n
    call push_item(heap,itemize(n))
    return
  end subroutine push
  function pop(heap) result(n)
    implicit none
    type(t_heap), intent(inout) :: heap
    type(t_item) :: item
    integer :: n
    item = pop_item(heap)
    n = item%n
    return
  end function pop
  function peek(heap) result(n)
    implicit none
    type(t_heap), intent(inout) :: heap
    type(t_item) :: item
    integer :: n
    item = peek_item(heap)
    n = item%n
    return
  end function peek
  subroutine poll(heap)
    implicit none
    type(t_heap), intent(inout) :: heap
    call poll_item(heap)
    return
  end subroutine poll
end module mod_t_priority_queue
program one_d_matching
  use mod_t_priority_queue
  implicit none
  type(t_heap) :: a, b
  integer(8), parameter :: md = 1000000007_8
  integer :: n, x, y, i
  integer(8) :: m
  call init_heap(a)
  call init_heap(b)
  read(*,*) n
  do i = 1, n
    read(*,*) x
    call push(a,x)
  end do
  do i = 1, n
    read(*,*) x
    call push(b,x)
  end do
  call push(a,2000000000)
  call push(b,2000000000)
  m = 1_8
  x = 0
  y = 0
  do while (size_of_heap(a).gt.1.or.size_of_heap(b).gt.1)
    if (peek(a).lt.peek(b)) then
      call poll(a)
      if (y.eq.0) then
        x = x+1
      else
        m = mod(m*int(y,8),md)
        y = y-1
      end if
    else
      call poll(b)
      if (x.eq.0) then
        y = y+1
      else
        m = mod(m*int(x,8),md)
        x = x-1
      end if
    end if
  end do
  write(*,'(i0)') m
  call release_heap(a)
  call release_heap(b)
  stop
end program one_d_matching