output_description: Print the maximum number of friendly pairs.
  
  * * *
input_description: Input is given from Standard Input in the following format:
  
      
      
      N
      a_1 b_1
      a_2 b_2
      :
      a_N b_N
      c_1 d_1
      c_2 d_2
      :
      c_N d_N
attempt: #!/usr/bin/env pypy3
  
  
  import collections
  import itertools
  import sys
  
  
  #: The value representing "infinity."
  INF = 10**8
  
  #: The maxium number of recursion.
  REC_LIMIT = 10000
  
  #: Named tuple representing a edge in the flow network in question.
  FlowEdge = collections.namedtuple("FlowEdge", "source sink capacity")
  
  
  class FlowNetwork(object):
      """Class representing a flow network.
  
      :param int num_vertices: The number of vertices in the network.
      """
  
      def __init__(self, num_vertices):
          self.adj_edges = [set() for _ in range(num_vertices)]
          self.flow = None
          self.rev_edge = dict()
          self.used = None
  
      def get_edges_from(self, vertex):
          """Returns the set of edges adjacent to the vertex.
  
          :param int vertex: The index of vertex.
          :returns: The set of edges adjacent to the vertex.
          :rtype: set
          """
  
          return self.adj_edges[vertex]
  
      def add_edge(self, source, sink, capacity):
          """Add an edge u -> v to the flow network.
  
          :param int source: The vertex u.
          :param int sink: The vertex v.
          :param int capacity: The capacity of the edge.
          """
  
          assert source != sink
          forward_edge = FlowEdge(source, sink, capacity)
          backward_edge = FlowEdge(sink, source, 0)
          self.rev_edge[forward_edge] = backward_edge
          self.rev_edge[backward_edge] = forward_edge
          self.adj_edges[source].add(forward_edge)
          self.adj_edges[sink].add(backward_edge)
  
      def dfs(self, source, sink, flow):
          """Finding augmenting paths using depth-first search.
  
          This method is not supposed to be used directly.
          Instead, use :meth:`FlowNetwork.ford_fulkerson`.
          """
  
          if source == sink:
              return flow
          self.used[source] = True
          for edge in self.get_edges_from(source):
              rest = edge.capacity - self.flow[edge]
              if self.used[edge.sink] or rest <= 0:
                  continue
              d = self.dfs(edge.sink, sink, min(flow, rest))
              if d > 0:
                  self.flow[edge] += d
                  self.flow[self.rev_edge[edge]] -= d
                  return d
          return 0
  
      def ford_fulkerson(self, source, sink):
          """Computing maximum flow using the Ford-Fulkerson algorithm.
  
          :param int source: The source.
          :param int sink: The sink.
          :return: Maximum flow.
          """
  
          self.flow = collections.defaultdict(int)
          max_flow = 0
          while True:
              self.used = collections.defaultdict(bool)
              df = self.dfs(source, sink, INF)
              if df == 0:
                  return max_flow
              else:
                  max_flow += df
  
  
  def compute_max_num_pairs(num_points, red_points, blue_points):
      network = FlowNetwork(2 + 2 * num_points)
      source_idx = 2 * num_points
      sink_idx = source_idx + 1
      # source -> each vertex
      # each vertex -> sink
      for i in range(num_points):
          network.add_edge(source_idx, i, 1)
          network.add_edge(num_points + i, sink_idx, 1)
      g = itertools.product(
          enumerate(red_points), enumerate(blue_points, start=num_points)
      )
      for (ri, (rx, ry)), (bi, (bx, by)) in g:
          if rx < bx and ry < by:
              network.add_edge(ri, bi, 1)
      res = network.ford_fulkerson(source_idx, sink_idx)
      return res
  
  
  def main():
      sys.setrecursionlimit(REC_LIMIT)
      num_points = int(input())
      red_points = [tuple(int(z) for z in input().split()) for _ in range(num_points)]
      blue_points = [tuple(int(z) for z in input().split()) for _ in range(num_points)]
      res = compute_max_num_pairs(num_points, red_points, blue_points)
      print(res)
  
  
  if __name__ == "__main__":
      main()
  
problem_description: Statement
  
  On a two-dimensional plane, there are N red points and N blue points. The
  coordinates of the i-th red point are (a_i, b_i), and the coordinates of the
  i-th blue point are (c_i, d_i).
  
  A red point and a blue point can form a _friendly pair_ when, the x-coordinate
  of the red point is smaller than that of the blue point, and the y-coordinate
  of the red point is also smaller than that of the blue point.
  
  At most how many friendly pairs can you form? Note that a point cannot belong
  to multiple pairs.
samples: [{"input": "3\n    2 0\n    3 1\n    1 3\n    4 2\n    0 4\n    5 5", "output": "2\n    \n\nFor example, you can pair (2, 0) and (4, 2), then (3, 1) and (5, 5).\n\n* * *"}, {"input": "3\n    0 0\n    1 1\n    5 2\n    2 3\n    3 4\n    4 5", "output": "2\n    \n\nFor example, you can pair (0, 0) and (2, 3), then (1, 1) and (3, 4).\n\n* * *"}, {"input": "2\n    2 2\n    3 3\n    0 0\n    1 1", "output": "0\n    \n\nIt is possible that no pair can be formed.\n\n* * *"}, {"input": "5\n    0 0\n    7 3\n    2 2\n    4 8\n    1 6\n    8 5\n    6 9\n    5 4\n    9 1\n    3 7", "output": "5\n    \n\n* * *"}, {"input": "5\n    0 0\n    1 1\n    5 5\n    6 6\n    7 7\n    2 2\n    3 3\n    4 4\n    8 8\n    9 9", "output": "4"}]