Problem:
 Score : 400 points    Problem 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.      Constraints  All input values are integers.  1 \leq N \leq 100  0 \leq a_i, b_i, c_i, d_i < 2N  a_1, a_2, ..., a_N, c_1, c_2, ..., c_N are all different.  b_1, b_2, ..., b_N, d_1, d_2, ..., d_N are all different.         Input 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       Output Print the maximum number of friendly pairs.        Sample Input 1 3
2 0
3 1
1 3
4 2
0 4
5 5      Sample Output 1 2  For example, you can pair (2, 0) and (4, 2) , then (3, 1) and (5, 5) .       Sample Input 2 3
0 0
1 1
5 2
2 3
3 4
4 5      Sample Output 2 2  For example, you can pair (0, 0) and (2, 3) , then (1, 1) and (3, 4) .       Sample Input 3 2
2 2
3 3
0 0
1 1      Sample Output 3 0  It is possible that no pair can be formed.       Sample Input 4 5
0 0
7 3
2 2
4 8
1 6
8 5
6 9
5 4
9 1
3 7      Sample Output 4 5       Sample Input 5 5
0 0
1 1
5 5
6 6
7 7
2 2
3 3
4 4
8 8
9 9      Sample Output 5 4

Solution (Python):
n=int(input())
red=[]
blue=[]
for i in range(n):
  a,b=map(int,input().split())
  red.append([a,b])
for j in range(n):
  a,b=map(int,input().split())
  blue.append([a,b])
blue.sort(key=lambda x:x[0])
red.sort(key=lambda x:x[1],reverse=True)

cnt=0
for x,y in blue:
  for i in range(n):
    if red[i][0]<x and red[i][1]<y:
      cnt+=1
      red[i][0]=float("INF")
      red[i][1]=float("INF")
      break
print(cnt)

Solution (Python):
from collections import deque
class mf_graph:
    n=1
    g=[[] for i in range(1)]
    pos=[]
    def __init__(self,N):
        self.n=N
        self.g=[[] for i in range(N)]
    def add_edge(self,From,To,cap):
        assert 0<=From and From<self.n
        assert 0<=To and To<self.n
        assert 0<=cap
        m=len(self.pos)
        self.pos.append((From,len(self.g[From])))
        self.g[From].append({"to":To,"rev":len(self.g[To]),"cap":cap})
        self.g[To].append({"to":From,"rev":len(self.g[From])-1,"cap":0})
        return m
    def get_edge(self,i):
        m=len(self.pos)
        assert 0<=i and i<m
        _e=self.g[self.pos[i][0]][self.pos[i][1]]
        _re=self.g[_e["to"]][_e["rev"]]
        return {"from":self.pos[i][0],
                "to":_e["to"],
                "cap":_e["cap"]+_re["cap"],
                "flow":_re["cap"]}
    def edges(self):
        m=len(self.pos)
        result=[]
        for i in range(m):
            result.append(self.get_edge(i))
        return result
    def change_edge(self,i,new_cap,new_flow):
        m=len(self.pos)
        assert 0<=i and i<m
        assert 0<=new_flow and new_flow<=new_cap
        _e=self.g[self.pos[i][0]][self.pos[i][1]]
        _re=self.g[_e["to"]][_e["rev"]]
        _e["cap"]=new_cap-new_flow
        _re["cap"]=new_flow
    def flow(self,s,t,flow_limit=(2**31)-1):
        assert 0<=s and s<self.n
        assert 0<=t and t<self.n
        level=[0 for i in range(self.n)]
        Iter=[0 for i in range(self.n)]
        que=deque([])
        def bfs():
            for i in range(self.n):
                level[i]=-1
            level[s]=0
            que=deque([])
            que.append(s)
            while(len(que)>0):
                v=que.popleft()
                for e in self.g[v]:
                    if e["cap"]==0 or level[e["to"]]>=0:continue
                    level[e["to"]]=level[v]+1
                    if e["to"]==t:return
                    que.append(e["to"])
        def dfs(func,v,up):
            if (v==s):return up
            res=0
            level_v=level[v]
            for i in range(Iter[v],len(self.g[v])):
                e=self.g[v][i]
                if (level_v<=level[e["to"]] or self.g[e["to"]][e["rev"]]["cap"]==0):continue
                d=func(func,e["to"],min(up-res,self.g[e["to"]][e["rev"]]["cap"]))
                if d<=0:continue
                self.g[v][i]["cap"]+=d
                self.g[e["to"]][e["rev"]]["cap"]-=d
                res+=d
                if res==up:break
            return res
        flow=0
        while(flow<flow_limit):
            bfs()
            if level[t]==-1:
                break
            for i in range(self.n):
                Iter[i]=0
            while(flow<flow_limit):
                f=dfs(dfs,t,flow_limit-flow)
                if not(f):break
                flow+=f
        return flow
    def min_cut(self,s):
        visited=[False for i in range(self.n)]
        que=deque([])
        que.append(s)
        while(len(que)>0):
            p=que.popleft()
            visited[p]=True
            for e in self.g[p]:
                if e["cap"] and not(visited[e["to"]]):
                    visited[e["to"]]=True
                    que.append(e["to"])
        return visited

N=int(input())
G=mf_graph(2*N+2)
s=2*N
t=2*N+1
a=[0 for i in range(N)]
b=[0 for i in range(N)]
c=[0 for i in range(N)]
d=[0 for i in range(N)]
for i in range(N):
    a[i],b[i]=map(int,input().split())
for i in range(N):
    c[i],d[i]=map(int,input().split())
for i in range(N):
    G.add_edge(s,i,1)
    G.add_edge(i+N,t,1)
for i in range(N):
    for j in range(N):
        if a[i]<c[j] and b[i]<d[j]:
            G.add_edge(i,N+j,1)
ans=G.flow(s,t)
print(ans)

Solution (Python):

class FordFulkerson:
  def __init__(self, N):
    self.N = N
    self.edge = [[] for i in range(N)]

  def add_edge(self, fr, to, cap):
    forward = [to, cap, None]
    forward[2] = backward = [fr, 0, forward]
    self.edge[fr].append(forward)
    self.edge[to].append(backward)

  def add_multi_edge(self, v1, v2, cap1, cap2):
    edge1 = [v2, cap1, None]
    edge1[2] = edge2 = [v1, cap2, edge1]
    self.edge[v1].append(edge1)
    self.edge[v2].append(edge2)

  def dfs(self, v, t, f):
    if v == t:
      return f
    used = self.used
    used[v] = 1
    for e in self.edge[v]:
      w, cap, rev = e
      if cap and not used[w]:
        d = self.dfs(w, t, min(f, cap))
        if d:
          e[1] -= d
          rev[1] += d
          return d
    return 0

  def flow(self, s, t):
    flow = 0
    f = INF = 10**9 + 7
    N = self.N
    while f:
      self.used = [0]*N
      f = self.dfs(s, t, INF)
      flow += f
    return flow

import sys
readline = sys.stdin.readline

N = int(input())
R = [list(map(int, input().split())) for _ in range(N)]
B = [list(map(int, input().split())) for _ in range(N)]
ff = FordFulkerson(2*N+2)
for v in range(1,N+1):
  ff.add_edge(0,v,1)
for v in range(N):
  ff.add_edge(1+N+v,2*N+1,1)
for u,(a,b) in enumerate(R):
  for v,(c,d) in enumerate(B):
    if a<c and b<d:
      ff.add_edge(1+u,1+N+v,1)
ans = ff.flow(0,2*N+1)
print(ans)

Solution (Python):
n = int(input())
ab=[]
for i in range(n):
    ab.append(list(map(int, input().split())))
ab = sorted(ab, key=lambda x:x[1], reverse=True)

cd=[]
for i in range(n):
    cd.append(list(map(int, input().split())))
cd = sorted(cd, key=lambda x:x[0])




ans = 0
for i in cd:
    for ji, j in enumerate(ab):
        if i[0]>j[0] and i[1]>j[1]:
            
            ans+=1
            ab.pop(ji)
            break;
print(ans, flush=True)

Solution (Python):
"""ABC091 2D Plane 2N Points diff:
"""

N = int(input())

ab = [tuple(map(int, input().split())) for _ in range(N)]
cd = [tuple(map(int, input().split())) for _ in range(N)]

ans_x = 0
cd.sort(key=lambda x: x[0])
ab.sort(key=lambda x: x[1], reverse=True)
ab_used = [0]*N
for i, (c, d) in enumerate(cd):
    for j, (a, b) in enumerate(ab):
        if not ab_used[j] and a < c and b < d:
            ab_used[j] = 1
            ans_x += 1
            break












print(ans_x)

Solution (Python):
"""ABC091 2D Plane 2N Points diff:
"""

N = int(input())

ab = [tuple(map(int, input().split())) for _ in range(N)]
cd = [tuple(map(int, input().split())) for _ in range(N)]

ans_x = 0
cd.sort(key=lambda x: x[0])
ab.sort(key=lambda x: x[1], reverse=True)
ab_used = [0]*N
for i, (c, d) in enumerate(cd):
    for j, (a, b) in enumerate(ab):
        if not ab_used[j] and a < c and b < d:
            ab_used[j] = 1
            ans_x += 1
            break

ans_y = 0
cd.sort(key=lambda x: x[1])
ab.sort(key=lambda x: x[0], reverse=True)
ab_used = [0]*N
for i, (c, d) in enumerate(cd):
    for j, (a, b) in enumerate(ab):
        if not ab_used[j] and a < c and b < d:
            ab_used[j] = 1
            ans_y += 1
            break

print(max(ans_x, ans_y))

Solution (Python):
N = int(input())
ab = [[int(i) for i in input().split()] for _ in range(N)]
cd = [[int(i) for i in input().split()] for _ in range(N)]
 
ab.sort(key = lambda x: x[1], reverse=True)
cd.sort()
 
x = 0
for c, d in cd:
    for a, b in ab:
        if a < c and b < d:
            x += 1
            ab.remove([a, b])
            break
 
print(x)

Solution (Python):
from heapq import heappop, heappush

N = int(input())
R = []
B = []
YFlag = [True]*(2*N)

for _ in range(N):
  a, b = map(int, input().split())
  R.append((a, b))

for _ in range(N):
  c, d = map(int, input().split())
  B.append((c, d))

B.sort()

ans = 0
for c, d in B:
  cand = []
  for a, b in R:
    if a < c and b < d and YFlag[b]:
      cand.append(b)
  if cand:
    ans += 1
    YFlag[max(cand)] = False

print(ans)

Solution (Python):
n = int(input())
red, blue = [], []
for _ in range(n):
    a, b = map(int, input().split())
    red.append([a, b, min(a, b)])
for _ in range(n):
    a, b = map(int, input().split())
    blue.append([a, b, min(a, b)])
    
red.sort(key=lambda x: x[1])
blue.sort(key=lambda x: x[0])
status = [False for _ in range(n)]
ans = 0
for i in range(n):
    for j in range(n-1, -1, -1):
        if not status[j]:
            if red[j][0] < blue[i][0] and red[j][1] < blue[i][1]:
                ans += 1
                status[j] = True
                break
print(ans)

Solution (Python):
n = int(input())
edges = [[] for _ in range(n)]
ab = [list(map(int, input().split())) for _ in range(n)]
cd = [list(map(int, input().split())) for _ in range(n)]
for i in range(n):
    a, b = ab[i]
    for j in range(n):
        c, d = cd[j]
        if a < c and b < d:
            edges[i].append(j)
matched = [-1] * n
def dfs(v):
    for u in edges[v]:
        if visited[u]:
            continue
        visited[u] = True
        if matched[u] == -1 or dfs(matched[u]):
            matched[u] = v
            return True
    return False

ans = 0
for s in range(n):
    visited = [False] * n
    if dfs(s):
        ans += 1
print(ans)

Solution (Python):
import math
from math import gcd,pi,sqrt
INF = float("inf")
MOD = 10**9 + 7

import sys
sys.setrecursionlimit(10**6)
import itertools
import bisect
from collections import Counter,deque
def i_input(): return int(input())
def i_map(): return map(int, input().split())
def i_list(): return list(i_map())
def i_row(N): return [i_input() for _ in range(N)]
def i_row_list(N): return [i_list() for _ in range(N)]
def s_input(): return input()
def s_map(): return input().split()
def s_list(): return list(s_map())
def s_row(N): return [s_input for _ in range(N)]
def s_row_str(N): return [s_list() for _ in range(N)]
def s_row_list(N): return [list(s_input()) for _ in range(N)]


def main():
    n = i_input()
    R = sorted([i_list() for _ in range(n)])
    B = sorted([i_list() for _ in range(n)])

    ans = 0
    for bx, by in B:
        C = [(y,x) for x,y in R if x<bx and y < by]
        if len(C) == 0:
            continue
        ans += 1
        C.sort(reverse=True)
        R.remove([C[0][1],C[0][0]])
    print(ans)


if __name__=="__main__":
    main()

Solution (Python):
n = int(input())
reds = sorted([list(map(int,input().split())) for i in range(n)],key=lambda reds: -reds[1])
blues = sorted([list(map(int,input().split())) for i in range(n)])

res = 0

for c,d in blues:
  for a,b in reds:
    if a<c and b<d:
      reds.remove([a,b])
      res+=1
      break
      
print(res)

Solution (Python):
import operator
import bisect

n=int(input())
red=[tuple(map(int,input().split())) for _ in range(n)]
blue=[tuple(map(int,input().split())) for _ in range(n)]

red.sort(key=operator.itemgetter(0,1))
blue.sort(key=operator.itemgetter(0,1))


count=0
for i in range(n):
  for j in reversed(range(len(red))):
    
    if not red:
      break
    if red[j][0]<blue[i][0]:
      tmp=red[:j+1]
      tmp.sort(key=lambda x:x[1],reverse=True)
      for t in tmp:
        if t[1]<blue[i][1]:
          count+=1
          red.pop(red.index(t))
          
          break
    else:
      continue
    break

print(count)

Solution (Python):
n = int(input())
aka = [[0 for i in range(2*n)] for j in range(2*n)]
for i in range(n):
    a, b = map(int,input().split())
    aka[a][b] = 1
ao = [tuple(map(int,input().split())) for i in range(n)]
ao.sort()
ans = 0
for x , y in ao:
    flag = False
    for j in reversed(range(y)):
        if flag:
            break
        for i in reversed(range(x)):
            if aka[i][j] == 1:
                ans += 1
                aka[i][j] = 0
                flag = True
                break
print(ans)

Solution (Python):
from collections import defaultdict
import sys
sys.setrecursionlimit(10**7)

class Ford_Fulkerson:
    def __init__(self,G,N,s,t):
        self.G,self.N,self.s,self.t=G,N,s,t
        self.max_f=self.Max_Flow(self.G,self.s,self.t)
        
    def dfs(self,G,v,t,f,used):
        if v==t:
            return f
        used[v]=True
        for nv,cap in G[v].items():
            if not used[nv] and cap>0:
                d=self.dfs(self.G,nv,t,min(f,cap),used)
                if d>0:
                    self.G[v][nv]-=d
                    self.G[nv][v]+=d
                    return d
        return 0

    def Max_Flow(self,G,s,t):
        flow=0
        while(True):
            used=[False]*(2*N+2)
            f=self.dfs(self.G,self.s,self.t,float('inf'),used)
            if f==0:
                return flow
            flow+=f

N=int(input())
G=[defaultdict(int) for i in range(2*N+2)]
arr=[]
for i in range(2*N):
    x,y=map(int,input().split())
    arr.append((x,y))

for i in range(N,2*N):
    for j in range(N):
        a,b=arr[i]
        c,d=arr[j]
        if a>c and b>d:
            G[i+1][j+1]=1
            G[j+1][i+1]=0
for i in range(1,2*N+1):
    if i>=N+1:
        G[0][i]=1
        G[i][0]=0
    else:
        G[i][2*N+1]=1
        G[2*N+1][i]=0

MF=Ford_Fulkerson(G,2*N+2,0,2*N+1)
print(MF.max_f)

Solution (Python):
from collections import defaultdict
import sys
sys.setrecursionlimit(10**7)

class Ford_Fulkerson:
    def __init__(self,G,N,s,t,check):
        self.G,self.N,self.s,self.t,self.check=G,N,s,t,check
        for v in range(self.N):
            if v==s or v==t:
                continue
            for nv,cap in self.G[v].items():
                self.G[nv][v]=0
            if self.check(v):
                self.G[s][v]=1
                self.G[v][s]=0
            else:
                self.G[v][t]=1
                self.G[t][v]=0
        self.max_f=self.Max_Flow(self.G,self.s,self.t)
        
    def dfs(self,G,v,t,f,used):
        if v==t:
            return f
        used[v]=True
        for nv,cap in G[v].items():
            if not used[nv] and cap>0:
                d=self.dfs(self.G,nv,t,min(f,cap),used)
                if d>0:
                    self.G[v][nv]-=d
                    self.G[nv][v]+=d
                    return d
        return 0

    def Max_Flow(self,G,s,t):
        flow=0
        while(True):
            used=[False]*(2*N+2)
            f=self.dfs(self.G,self.s,self.t,float('inf'),used)
            if f==0:
                return flow
            flow+=f

N=int(input())
G=[defaultdict(int) for i in range(2*N+2)]
arr=[]
for i in range(2*N):
    x,y=map(int,input().split())
    arr.append((x,y))

for i in range(N,2*N):
    for j in range(N):
        a,b=arr[i]
        c,d=arr[j]
        if a>c and b>d:
            G[i+1][j+1]=1

def check(i):return i>=1+N
MF=Ford_Fulkerson(G,2*N+2,0,2*N+1,check)
print(MF.max_f)

Solution (Python):
from collections import defaultdict
import sys
sys.setrecursionlimit(10**7)
def dfs(v,t,f,used):
    if v==t:
        return f
    used[v]=True
    for nv,cap in G[v].items():
        if not used[nv] and cap>0:
            d=dfs(nv,t,min(f,cap),used)
            if d>0:
                G[v][nv]-=d
                G[nv][v]+=d
                return d
    return 0

def Max_Flow(s,t):
    flow=0
    while(True):
        used=[False]*(2*N+2)
        f=dfs(s,t,INF,used)
        if f==0:
            return flow
        flow+=f

INF=float('inf')

N=int(input())
G=[defaultdict(int) for i in range(2*N+2)]
arr=[]
for i in range(2*N):
    x,y=map(int,input().split())
    arr.append((x,y))

for i in range(N,2*N):
    for j in range(N):
        a,b=arr[i]
        c,d=arr[j]
        if a>c and b>d:
            G[i+1][j+1]=1
            G[j+1][i+1]=0

for i in range(N):
    G[0][N+i+1]=1
    G[N+i+1][0]=0
    G[i+1][2*N+1]=1
    G[2*N+1][i+1]=0
res=Max_Flow(0,2*N+1)
print(res)

Solution (Python):
import sys
from collections import deque
input = sys.stdin.readline

class Dinic:
    def __init__(self, v):
        self.vertice = v
        self.inf = int(1e9)
        self.graph = [[] for i in range(v)]
        self.level = [0]*v
        self.iter = [0]*v
    
    def add_edge(self, fr, to, cap):
        self.graph[fr].append([to, cap, len(self.graph[to])])
        self.graph[to].append([fr, 0, len(self.graph[fr])-1])
    
    def bfs(self, s):
        self.level = [-1]*self.vertice
        que = deque([])
        self.level[s] = 0
        que.append(s)

        while que:
            v = que.popleft()
            for i in range(len(self.graph[v])):
                e = self.graph[v][i]
                if e[1] > 0 and self.level[e[0]] < 0:
                    self.level[e[0]] = self.level[v] + 1
                    que.append(e[0])
    
    def dfs(self, v, t, f):
        if v == t:
            return f
        for i in range(self.iter[v], len(self.graph[v])):
            self.iter[v] = i
            e = self.graph[v][i]
            if e[1] > 0 and self.level[v] < self.level[e[0]]:
                d = self.dfs(e[0], t, min(f, e[1]))
                if d > 0:
                    e[1] -= d
                    self.graph[e[0]][e[2]][1] += d
                    return d
        return 0
    
    def max_flow(self, s, t):
        flow = 0
        while True:
            self.bfs(s)
            if self.level[t] < 0:
                return flow
            self.iter = [0]*self.vertice

            f = self.dfs(s, t, self.inf)
            while f:
                flow += f
                f = self.dfs(s, t, self.inf)
    
def main():
    n = int(input())
    red = [list(map(int, input().split())) for _ in range(n)]
    blue = [list(map(int, input().split())) for _ in range(n)]
    
    flow = Dinic(n*2+2)
    for i in range(n):
        flow.add_edge(0, i+1, 1)
        flow.add_edge(n+i+1, 2*n+1, 1)
        for j in range(n):
            if red[i][0] < blue[j][0] and red[i][1] < blue[j][1]:
                flow.add_edge(i+1, n+j+1, 1)
    
    
    ans = flow.max_flow(0, 2*n+1)
    print(ans)
    
if __name__ == "__main__":
    main()

Solution (Python):
N = int(input())

reds = []
for i in range(N):
    a, b = map(int, input().split())
    reds.append([a,b])
reds.sort(key=lambda x: x[1], reverse=True)

blues = []
for i in range(N):
    c, d = map(int, input().split())
    blues.append([c,d])
blues.sort()

flag = [False for i in range(N)]
ans = 0
for i in range(N):
    c, d = blues[i][0], blues[i][1]
    for j in range(N):
        if flag[j] == True:
            continue
        a, b = reds[j][0], reds[j][1]
        if c>a and d>b:
            flag[j] = True
            ans += 1
            break
print(ans)

Solution (Python):
import networkx as nx

N = int(input())
ABs = [tuple(map(int, input().split())) for _ in range(N)]
CDs = [tuple(map(int, input().split())) for _ in range(N)]






DG = nx.DiGraph()
DG.add_nodes_from(range(2 * N + 3))
for i in range(N):
    for j in range(N):
        if ABs[i][0] < CDs[j][0] and ABs[i][1] < CDs[j][1]:
            DG.add_edge(i, j + N, capacity = 1)

DG.add_edges_from([(2 * N + 1, i, {"capacity":1}) for i in range(N)])
DG.add_edges_from([(i, 2 * N + 2, {"capacity":1}) for i in range(N, 2*N)])

print(nx.maximum_flow_value(DG, 2 * N + 1, 2 * N + 2))

Solution (Python):
def main():
    from sys import stdin
    def input():
        return stdin.readline().strip()
    
    n = int(input())
    red = [tuple(map(int, input().split())) for _ in range(n)]
    blue = [tuple(map(int, input().split())) for _ in range(n)]

    red.sort()
    blue.sort()

    now = 0
    for i in blue:
        while now < len(red) and red[now] < i:
            now += 1
        
        l = red[:now]
        if l == []:
            continue

        l = sorted(l, key=lambda x: x[1])
        if l[0][1] > i[1]:
            continue
        
        
        left = 0
        right = len(l) - 1
        while left < right:
            center = (left + right + 1) // 2
            if l[center][1] < i[1]:
                left = center
            else:
                right = center - 1

        red.remove(l[left])
        now -= 1

    print(n - len(red))

main()

Solution (Python):
def main():
    from sys import stdin
    def input():
        return stdin.readline().strip()
    
    n = int(input())
    red = [tuple(map(int, input().split())) for _ in range(n)]
    blue = [tuple(map(int, input().split())) for _ in range(n)]

    red.sort()
    blue.sort()

    now = 0
    for i in blue:
        while now < len(red) and red[now] < i:
            now += 1
        
        l = red[:now]
        if l == []:
            continue

        l = sorted(l, key=lambda x: x[1])
        if l[0][1] > i[1]:
            continue
        
        
        left = 0
        right = len(l) - 1
        while left < right:
            center = (left + right + 1) // 2
            if l[center][1] < i[1]:
                left = center
            else:
                right = center - 1

        red.remove(l[left])
        now -= 1

    print(n - len(red))

main()

Solution (Python):
def main():
    from sys import stdin
    def input():
        return stdin.readline().strip()
    
    n = int(input())
    red = [tuple(map(int, input().split())) for _ in range(n)]
    blue = [tuple(map(int, input().split())) for _ in range(n)]

    red.sort()
    blue.sort()

    now = 0
    for i in blue:
        while now < len(red) and red[now] < i:
            now += 1
        
        l = red[:now]
        if l == []:
            continue

        l = sorted(l, key=lambda x: x[1])
        for j in range(len(l)-1, -1, -1):
            if l[j][1] < i[1]:
                red.remove(l[j])
                now -= 1
                break

    print(n - len(red))

main()

Solution (Python):


import sys 
from bisect import bisect,bisect_left
read = sys.stdin.buffer.read
readline = sys.stdin.buffer.readline
readlines = sys.stdin.buffer.readlines
N = int(readline())
query = [(0,0)]*N*2

for _ in range(N):
    a,b =map(int,readline().split())
    query[a] = (0,b)
for _ in range(N):
    a,b =map(int,readline().split())
    query[a] = (1,b)

A = []
ans = 0
for i in range(2*N):
    q,y = query[i]
    if q == 0:
        A.append(y)
        A = sorted(A)
    else:
        ind = bisect_left(A,y)
        if ind != 0:
            A.pop(ind-1)
            ans += 1
print(ans)

Solution (Python):


import networkx as nx


n = int(input())
ab = [list(map(int, input().split())) for i in range(n)]
cd = [list(map(int, input().split())) for i in range(n)]


match_list = [[] for i in range(n)]
for i in range(n):
    for j in range(n):
        a, b = ab[i]
        c, d = cd[j]

        if a < c and b < d:
            match_list[i].append(j)



group1 = range(n)
group2 = range(n, 2*n)

g = nx.Graph()
g.add_nodes_from(group1, bipartite=1)
g.add_nodes_from(group2, bipartite=0)

for i, list_ in enumerate(match_list):
    for j in list_:
        g.add_edge(i, j+n, weight=1)












d = nx.max_weight_matching(g)

print(len(d))

Solution (Python):
def abc091_c():
    n = int(input())
    red = []
    blue = []
    for _ in range(n):
        a, b = (int(x) for x in input().split())
        red.append((a, b))
    for _ in range(n):
        c, d = (int(x) for x in input().split())
        blue.append((c, d))
    blue = sorted(blue, key=lambda x: x[0])

    ans = 0
    r_used = [False]*n
    for c, d in blue:
        match = -1
        y_high = -1
        for i, (a, b) in enumerate(red):
            if r_used[i]: continue
            if not (a < c and b < d): continue
            if y_high < b:
                match = i
                y_high = b
        if match != -1:
            ans += 1
            r_used[match] = True
    print(ans)

if __name__ == '__main__':
    abc091_c()

Solution (Python):
N = int(input())
Red = sorted([tuple(map(int, input().split())) for _ in range(N)])
Blue = sorted([tuple(map(int, input().split())) for _ in range(N)])

ans = 0
for bx,by in Blue:
    C = [(y,x) for x,y in Red if x<bx and y<by] 
    if len(C) == 0:
        continue
    ans += 1
    C.sort(reverse=True)
    Red.remove((C[0][1],C[0][0]))
print(ans)

Solution (Python):

n = int(input().strip())
red = [list(map(int, input().split())) for i in range(n)]
blue = [list(map(int, input().split())) for j in range(n)]

for i in range(n):
    '''
    kagi_r = [min(red[i][0], red[i][1]), max(red[i][0], red[i][1])]
    kagi_b = [min(blue[i][0], blue[i][1]), max(blue[i][0], blue[i][1])]
    red[i] = red[i] + kagi_r
    blue[i] = blue[i] + kagi_b
    '''
red.sort(key=lambda x: (x[0], x[1]), reverse=True)
blue.sort(key=lambda x: x[1])
flg_r = [0]*n
cnt = 0

for i in range(n):
    for j in range(n):
        if flg_r[j]:
            continue
        if red[j][0] < blue[i][0] and red[j][1] < blue[i][1]:
            flg_r[j] = 1
            cnt += 1
            break

print(cnt)

Solution (Python):
n = int(input())
ab = []
for i in range(n):
    ab.append(list(map(int, input().split())))
cd = []
for i in range(n):
    cd.append(list(map(int, input().split())))
cd.sort()
ab.sort(key = lambda x: x[1], reverse = True)
flag_ab = [False for i in range(n)]
count = 0
for i in range(n):
    c, d = cd[i][0], cd[i][1]
    for j in range(n):
        if flag_ab[j] == True:
            continue
        a, b = ab[j][0], ab[j][1]
        if c > a and d > b:
            flag_ab[j] = True
            count += 1
            break
print(count)

Solution (Python):
n=int(input())
red=[[] for i in range(n)]
blue=[[] for i in range(n)]
for i in range(n):
    a,b=map(int,input().split())
    red[i].append(a)
    red[i].append(b)
for i in range(n):
    a,b=map(int,input().split())
    blue[i].append(a)
    blue[i].append(b)
red=sorted(red)
blue=sorted(blue)
ans=0
for i in range(n):
    x=blue[i][0]
    y=blue[i][1]
    maxy=-1
    for j in range(n):
        if x>red[j][0] and y>red[j][1]:
            maxy=max(maxy,red[j][1])
    for j in range(n):
        if x>red[j][0] and maxy==red[j][1]:
            ans+=1
            red[j][0]=1000
            break
print(ans)

Solution (Python):
n=int(input())
red=[[] for i in range(n)]
blue=[[] for i in range(n)]
for i in range(n):
    a,b=map(int,input().split())
    red[i].append(a)
    red[i].append(b)
for i in range(n):
    a,b=map(int,input().split())
    blue[i].append(a)
    blue[i].append(b)
red=sorted(red)
blue=sorted(blue)
ans=0
for i in range(n):
    x=blue[i][0]
    y=blue[i][1]
    maxy=-1
    for j in range(n):
        if x>red[j][0] and y>red[j][1]:
            maxy=max(maxy,red[j][1])
    for j in range(n):
        if x>red[j][0] and maxy==red[j][1]:
            ans+=1
            red[j][0]=1000
            break
print(ans)

Solution (Python):
n=int(input())
red=[[] for i in range(n)]
blue=[[] for i in range(n)]
for i in range(n):
    a,b=map(int,input().split())
    red[i].append(a)
    red[i].append(b)
for i in range(n):
    a,b=map(int,input().split())
    blue[i].append(a)
    blue[i].append(b)
red=sorted(red)
blue=sorted(blue)
ans=0
for i in range(n):
    x=blue[i][0]
    y=blue[i][1]
    maxy=-1
    for j in range(n):
        if x>red[j][0] and y>red[j][1]:
            maxy=max(maxy,red[j][1])
    for j in range(n):
        if x>red[j][0] and maxy==red[j][1]:
            ans+=1
            red[j][0]=1000
            break
print(ans)

Solution (Python):

(n, ), *dot = [[*map(int, i.split())] for i in open(0)]
red = sorted(dot[:n])
blue = sorted(dot[n:])
for c, d in blue:
    o = [[a, b] for a, b in red if a < c and b < d]
    if o:
        red.remove(max(o, key=lambda x: x[1]))
print(n - len(red))

Solution (Python):
N = int(input())
red = [list(map(int, input().split())) for _ in range(N)]
blue = [list(map(int, input().split())) for _ in range(N)]


blue.sort(key=lambda x: x[1])


red.sort(key=lambda x: x[0], reverse=True)

red_list = [0] * N

for b in range(N):
    for r in range(N):
        if red_list[r] == 1:
            continue
        if red[r][0] < blue[b][0] and red[r][1] < blue[b][1]:
            red_list[r] = 1
            break

print(sum(red_list))

Solution (Python):
N = int(input())
red = [list(map(int, input().split())) for _ in range(N)]
blue = [list(map(int, input().split())) for _ in range(N)]


blue.sort(key=lambda x: x[1])


red.sort(reverse=True)





red_list = [0] * N


for b in range(N):
    for r in range(N):
        if red_list[r] == 1:
            continue
        if red[r][0] < blue[b][0] and red[r][1] < blue[b][1]:
            
            
            red_list[r] = 1
            break

print(sum(red_list))

Solution (Python):
N = int(input())
red = [list(map(int, input().split())) for _ in range(N)]
blue = [list(map(int, input().split())) for _ in range(N)]


blue.sort(key=lambda x: x[1])


red.sort(reverse=True)




blue_list = [0] * N
red_list = [0] * N


for b in range(N):
    for r in range(N):
        if red_list[r] == 1:
            continue
        if red[r][0] < blue[b][0] and red[r][1] < blue[b][1]:
            
            blue_list[b] = 1
            red_list[r] = 1
            break

print(sum(blue_list))

Solution (Python):
N = int(input())
red = [list(map(int, input().split())) for _ in range(N)]
blue = [list(map(int, input().split())) for _ in range(N)]

red.sort(reverse=True)

blue.sort(key=lambda x: x[1])



blue_list = [0] * N
red_list = [0] * N


for b in range(N):
    for r in range(N):
        if blue_list[b] == 1 or red_list[r] == 1:
            continue
        if red[r][0] < blue[b][0] and red[r][1] < blue[b][1]:
            
            blue_list[b] = 1
            red_list[r] = 1
            break

print(sum(blue_list))

Solution (Python):
n=int(input())
R=sorted([list(map(int,input().split())) for i in range(n)], key=lambda R: -R[1])
B=sorted([list(map(int,input().split())) for i in range(n)])
ans=0
for c,d in B:
  for a,b in R:
    if a<c and b<d:
      R.remove([a,b]);ans+=1
      break
print(ans)