Problem:
Score : 1000 points

Problem Statement

There are M chairs arranged in a line. The coordinate of the i-th chair (1 ≤ i ≤ M) is i.

N people of the Takahashi clan played too much games, and they are all suffering from backaches. They need to sit in chairs and rest, but they are particular about which chairs they sit in. Specifically, the i-th person wishes to sit in a chair whose coordinate is not greater than L_i, or not less than R_i. Naturally, only one person can sit in the same chair.

It may not be possible for all of them to sit in their favorite chairs, if nothing is done.
Aoki, who cares for the health of the people of the Takahashi clan, decides to provide additional chairs so that all of them can sit in chairs at their favorite positions.

Additional chairs can be placed at arbitrary real coordinates. Find the minimum required number of additional chairs.

Constraints

1 ≤ N,M ≤ 2 × 10^5

0 ≤ L_i < R_i ≤ M + 1(1 ≤ i ≤ N)

All input values are integers.

Input

Input is given from Standard Input in the following format:

N M
L_1 R_1
:
L_N R_N

Output

Print the minimum required number of additional chairs.

Sample Input 1

4 4
0 3
2 3
1 3
3 4

Sample Output 1

0

The four people can sit in chairs at the coordinates 3, 2, 1 and 4, respectively, and no more chair is needed.

Sample Input 2

7 6
0 7
1 5
3 6
2 7
1 6
2 6
3 7

Sample Output 2

2

If we place additional chairs at the coordinates 0 and 2.5, the seven people can sit at coordinates 0, 5, 3, 2, 6, 1 and 2.5, respectively.

Sample Input 3

3 1
1 2
1 2
1 2

Sample Output 3

2

Sample Input 4

6 6
1 6
1 6
1 5
1 5
2 6
2 6

Sample Output 4

2

Solution in Lua (LuaJIT 2.1.0) (judge verdict: Time Limit Exceeded)

local mma = math.max
local mfl, mce, mmi = math.floor, math.ceil, math.min
local MPM = {}
MPM.initialize = function(self, n, spos, tpos)
  self.n = n
  self.spos, self.tpos = spos, tpos
  -- edge_dst[src][i] := dst
  self.edge_dst = {}
  -- edge_cap[src][i] := capacity from src to edge_dst[src][i]
  self.edge_cap = {}
  -- edge_dst_invedge_idx[src][i] := "j" where edge_dst[dst][j] == src
  -- in this case, edge_dst_invedge_idx[dst][j] should be "i".
  self.edge_dst_invedge_idx = {}
  -- level[v] := length from spos. level[spos] := 1
  self.level = {}
  -- level_vertex_count[i] := count of vertexes that levels are i
  self.level_vertex_count = {}
  -- sub_graph_v[i] := list of vertexes that are contained in the sub-graph.
  self.sub_graph_v = {}
  -- sub_graph_size := the size of sub_graph_v.
  -- may not equal to #sub_graph_v (because not cleared).
  self.sub_graph_size = 0
  -- sub_graph_flag[v] := whether to contains the vertex v in the sub-graph or not
  self.sub_graph_flag = {}
  -- send[v] := sum of sendable amount from v to other vertexes in the sub-graph
  self.send = {}
  -- receive[v] := sum of receivable amount toward v from other vertexes in the sub-graph
  self.receive = {}
  -- sub_edge_idxes[src][i] := edge (from v) using in the sub-graph.
  -- for example, if sub_edge_idxes[src][i] is j,
  -- the edge from src to dst (= edge_dst[src][j]) contains in the sub-graph.
  self.sub_edge_idxes = {}
  -- sub_edge_cnt[src] := the size of sub_edge_idxes[src].
  -- may not equal to #sub_edge_idxes[src] (because not cleared).
  self.sub_edge_cnt = {}
  -- sub_invedge_idxes[dst] := edge (to dst) using in the sub-graph.
  -- for example, if sub_invedge_idxes[dst][i] is j,
  -- the src is edge_dst[dst][j], and the edge index (from src to dst) is k := edge_dst_invedge_idx[dst][j].
  -- so edge_dst[src][k] is the edge from src to dst using in the sub-graph.
  self.sub_invedge_idxes = {}
  -- sub_invedge_cnt[dst] := the size of sub_invedge_idxes[dst].
  -- may not equal to #sub_invedge_idxes[dst] (because not cleared).
  self.sub_invedge_cnt = {}
  -- flow_route[v] := [for "flowToT"] whether to contain in the route from weak_vertex to tpos.
  self.flow_route = {}
  -- actual_flow_amount[v] := [for "flowToT"] send amount from v
  self.actual_flow_amount = {}
  for i = 1, n do
    self.edge_dst[i] = {}
    self.edge_cap[i] = {}
    self.edge_dst_invedge_idx[i] = {}
    self.level[i] = 0
    self.level_vertex_count[i] = 0
    self.sub_graph_flag[i] = false
    self.send[i] = 0
    self.receive[i] = 0
    self.sub_edge_idxes[i] = {}
    self.sub_edge_cnt[i] = 0
    self.sub_invedge_idxes[i] = {}
    self.sub_invedge_cnt[i] = 0
    self.flow_route[i] = false
    self.actual_flow_amount[i] = 0
  end
end

MPM.addEdge = function(self, src, dst, cap, invcap)
  if not invcap then invcap = 0 end
  table.insert(self.edge_dst[src], dst)
  table.insert(self.edge_cap[src], cap)
  table.insert(self.edge_dst_invedge_idx[src], 1 + #self.edge_dst[dst])
  table.insert(self.edge_dst[dst], src)
  table.insert(self.edge_cap[dst], invcap)
  table.insert(self.edge_dst_invedge_idx[dst], #self.edge_dst[src])
end
MPM.makeSubGraph = function(self)
  local inf = self.n + 2
  local level, sub_graph_flag = self.level, self.sub_graph_flag
  local edge_dst, edge_cap = self.edge_dst, self.edge_cap
  local edge_dst_invedge_idx = self.edge_dst_invedge_idx
  local send, receive = self.send, self.receive
  local sub_graph_v = self.sub_graph_v
  local sub_edge_idxes, sub_edge_cnt = self.sub_edge_idxes, self.sub_edge_cnt
  local sub_invedge_idxes, sub_invedge_cnt = self.sub_invedge_idxes, self.sub_invedge_cnt
  local level_vertex_count = self.level_vertex_count
  for i = 1, self.n do
    level[i] = inf
    sub_graph_flag[i] = false
    send[i], receive[i] = 0, 0
    sub_edge_cnt[i] = 0
    sub_invedge_cnt[i] = 0
    level_vertex_count[i] = 0
  end
  -- BFS
  level[self.spos] = 1
  local taskcnt, done = 1, 0
  sub_graph_v[1] = self.spos
  local reached = false
  while done < taskcnt do
    done = done + 1
    local src = sub_graph_v[done]
    if src == self.tpos then reached = true break end
    for i = 1, #edge_dst[src] do
      local cap = edge_cap[src][i]
      if 0 < cap then
        local dst = edge_dst[src][i]
        if level[dst] == inf then
          level[dst] = level[src] + 1
          taskcnt = taskcnt + 1
          sub_graph_v[taskcnt] = dst
        elseif level[dst] == level[src] + 1 then
        end
      end
    end
  end
  if not reached then
    self.sub_graph_size = 0
    return false
  end
  -- restore route
  sub_graph_flag[self.tpos] = true
  local curlevel = level[self.tpos]
  while curlevel == level[sub_graph_v[taskcnt]] do
    taskcnt = taskcnt - 1
  end
  for isrc = taskcnt, 1, -1 do
    local src = sub_graph_v[isrc]
    for i = 1, #edge_dst[src] do
      local dst, cap = edge_dst[src][i], edge_cap[src][i]
      if 0 < cap and sub_graph_flag[dst]
      and level[dst] == level[src] + 1 then
        sub_graph_flag[src] = true
        local edgecnt = sub_edge_cnt[src] + 1
        sub_edge_cnt[src] = edgecnt
        sub_edge_idxes[src][edgecnt] = i
        sub_invedge_cnt[dst] = sub_invedge_cnt[dst] + 1
        sub_invedge_idxes[dst][sub_invedge_cnt[dst]] = edge_dst_invedge_idx[src][i]
        send[src] = send[src] + cap
        receive[dst] = receive[dst] + cap
      end
    end
    if not sub_graph_flag[src] then
      for i = 1, #edge_dst[src] do
        local dst = edge_dst[src][i]
        local cap = edge_cap[src][i]
        if 0 < cap and level[dst] == level[src] + 1 then
          send[src] = send[src] - cap
          receive[dst] = receive[dst] - cap
        end
      end
    end
  end
  -- remove unused vertex from "taskcnt" and set as sub_graph_size
  local nodecnt = 1
  for i = 1, taskcnt do
    local v = sub_graph_v[i]
    if sub_graph_flag[v] then
      sub_graph_v[nodecnt] = v
      local lv = level[v]
      level_vertex_count[lv] = level_vertex_count[lv] + 1
      nodecnt = nodecnt + 1
    end
  end
  if sub_graph_v[nodecnt - 1] == self.tpos then
    nodecnt = nodecnt - 1
  else
    sub_graph_v[nodecnt] = self.tpos
    local lv = level[self.tpos]
    level_vertex_count[lv] = level_vertex_count[lv] + 1
  end
  self.sub_graph_size = nodecnt
  return true
end

MPM.subGraphConnected = function(self)
  local max_level = self.level[self.tpos]
  local level_vertex_count = self.level_vertex_count
  for i = 1, max_level do
    if level_vertex_count[i] <= 0 then return false end
  end
  return true
end

MPM.findWeakVertex = function(self)
  local sub_graph_v = self.sub_graph_v
  local sub_graph_size = self.sub_graph_size
  local send, receive = self.send, self.receive
  local min_vertex = self.spos
  local min_potential = send[min_vertex]
  if receive[self.tpos] < min_potential then
    min_vertex = self.tpos
    min_potential = receive[min_vertex]
  end
  for i = 2, sub_graph_size - 1 do
    local v = sub_graph_v[i]
    local min_v = mmi(send[v], receive[v])
    if min_v < min_potential then
      min_potential, min_vertex = min_v, v
    end
  end
  return min_vertex, min_potential
end

MPM.flowToT = function(self, weak_vertex, potential)
  if weak_vertex == self.tpos then return end
  local sub_graph_flag = self.sub_graph_flag
  local edge_dst, edge_cap = self.edge_dst, self.edge_cap
  local edge_dst_invedge_idx = self.edge_dst_invedge_idx
  local sub_graph_v = self.sub_graph_v
  local sub_graph_size = self.sub_graph_size
  local sub_edge_cnt = self.sub_edge_cnt
  local sub_edge_idxes = self.sub_edge_idxes
  local send, receive = self.send, self.receive
  local level = self.level
  local flow_route = self.flow_route
  local actual_flow_amount = self.actual_flow_amount
  local tpos = self.tpos
  for i = 1, sub_graph_size do
    local v = sub_graph_v[i]
    flow_route[v] = false
    actual_flow_amount[v] = 0
  end
  flow_route[weak_vertex] = true
  actual_flow_amount[weak_vertex] = potential
  local weak_vertex_level = level[weak_vertex]
  local max_level = level[tpos]
  for iv = 1, sub_graph_size do
    local src = sub_graph_v[iv]
    local lv = level[src]
    if lv == max_level then break end
    local need_to_send = actual_flow_amount[src]
    if flow_route[src] and 0 < need_to_send then
      send[src] = send[src] - need_to_send
      local sub_edge_idxes_src = sub_edge_idxes[src]
      local dsts, caps, invidxes = edge_dst[src], edge_cap[src], edge_dst_invedge_idx[src]
      local used = 0
      -- use edge in descending order, to remove used edges quickly
      for j = sub_edge_cnt[src], 1, -1 do
        local edgeidx = sub_edge_idxes_src[j]
        local dst, cap = dsts[edgeidx], caps[edgeidx]
        local actual_flow = mmi(cap, need_to_send)
        receive[dst] = receive[dst] - actual_flow
        caps[edgeidx] = caps[edgeidx] - actual_flow
        need_to_send = need_to_send - actual_flow
        flow_route[dst] = true
        actual_flow_amount[dst] = actual_flow_amount[dst] + actual_flow
        local inv_edge_idx = invidxes[edgeidx]
        edge_cap[dst][inv_edge_idx] = edge_cap[dst][inv_edge_idx] + actual_flow
        if caps[edgeidx] == 0 then
          used = used + 1
        end
        if need_to_send == 0 then
          break
        end
      end
      sub_edge_cnt[src] = sub_edge_cnt[src] - used
    end
  end
end

MPM.flowFromS = function(self, weak_vertex, potential)
  if weak_vertex == self.spos then return end
  local sub_graph_flag = self.sub_graph_flag
  local edge_dst, edge_cap = self.edge_dst, self.edge_cap
  local edge_dst_invedge_idx = self.edge_dst_invedge_idx
  local sub_graph_v = self.sub_graph_v
  local sub_graph_size = self.sub_graph_size
  local sub_edge_cnt = self.sub_edge_cnt
  local sub_edge_idxes = self.sub_edge_idxes
  local sub_invedge_idxes = self.sub_invedge_idxes
  local sub_invedge_cnt = self.sub_invedge_cnt
  local send, receive = self.send, self.receive
  local level = self.level
  local flow_route = self.flow_route
  local actual_flow_amount = self.actual_flow_amount
  local spos = self.spos
  for i = 1, sub_graph_size do
    local v = sub_graph_v[i]
    flow_route[v] = false
    actual_flow_amount[v] = 0
  end
  flow_route[weak_vertex] = true
  actual_flow_amount[weak_vertex] = potential
  local weak_vertex_level = level[weak_vertex]
  local max_level = level[tpos]
  for iv = sub_graph_size, 1, -1 do
    local dst = sub_graph_v[iv]
    local lv = level[dst]
    if lv == 1 then break end
    local need_to_receive = actual_flow_amount[dst]
    if flow_route[dst] and 0 < need_to_receive then
      receive[dst] = receive[dst] - need_to_receive
      local sub_invedge_idxes_dst = sub_invedge_idxes[dst]
      local srcs = edge_dst[dst]
      local inv_invidxes = edge_dst_invedge_idx[dst]
      -- local dsts, caps, invidxes = edge_dst[src], edge_cap[src], edge_dst_invedge_idx[src]
      local used = 0
      -- use edge in descending order, to remove used edges quickly
      for j = sub_invedge_cnt[dst], 1, -1 do
        local invedgeidx = sub_invedge_idxes_dst[j]
        local src = srcs[invedgeidx]
        local edgeidx = inv_invidxes[invedgeidx]
        assert(edge_dst[src][edgeidx] == dst)
        local cap = edge_cap[src][edgeidx]
        local actual_flow = mmi(cap, need_to_receive)

        send[src] = send[src] - actual_flow
        edge_cap[src][edgeidx] = edge_cap[src][edgeidx] - actual_flow
        need_to_receive = need_to_receive - actual_flow
        flow_route[src] = true
        actual_flow_amount[src] = actual_flow_amount[src] + actual_flow
        edge_cap[dst][invedgeidx] = edge_cap[dst][invedgeidx] + actual_flow
        if edge_cap[src][edgeidx] == 0 then
          used = used + 1
        end
        if need_to_receive == 0 then
          break
        end
      end
      sub_invedge_cnt[dst] = sub_invedge_cnt[dst] - used
    end
  end
end

MPM.updateSubGraph = function(self)
  local sub_graph_v = self.sub_graph_v
  local sub_graph_size = self.sub_graph_size
  local sub_graph_flag = self.sub_graph_flag
  local send, receive = self.send, self.receive
  local spos, tpos = self.spos, self.tpos
  local level = self.level
  local level_vertex_count = self.level_vertex_count
  local sub_edge_idxes = self.sub_edge_idxes
  local sub_edge_cnt = self.sub_edge_cnt
  local edge_dst = self.edge_dst
  local sub_invedge_idxes = self.sub_invedge_idxes
  local sub_invedge_cnt = self.sub_invedge_cnt
  local nodecnt = 0
  for i = 1, sub_graph_size do
    local v = sub_graph_v[i]
    local valid = true
    if v ~= spos and receive[v] <= 0 then valid = false end
    if v ~= tpos and send[v] <= 0 then valid = false end
    if valid then
      local sub_invedge_idxes_v = sub_invedge_idxes[v]
      valid = false
      for j = 1, sub_invedge_cnt[v] do
        local ei = sub_invedge_idxes_v[j]
        local src = edge_dst[v][ei]
        if sub_graph_flag[src] then valid = true break end
      end
    end
    if valid then
      nodecnt = nodecnt + 1
      sub_graph_v[nodecnt] = v
    else
      sub_graph_flag[v] = false
      local lv = level[v]
      level_vertex_count[lv] = level_vertex_count[lv] - 1
    end
  end
  sub_graph_size = nodecnt
  for i = sub_graph_size, 1, -1 do
    local v = sub_graph_v[i]
    local valid = false
    local sub_edge_idxes_v = sub_edge_idxes[v]
    for j = 1, sub_edge_cnt[v] do
      local ei = sub_edge_idxes_v[j]
      local dst = edge_dst[v][ei]
      if sub_graph_flag[dst] then valid = true break end
    end
    if not valid then
      sub_graph_flag[v] = false
      local lv = level[v]
      level_vertex_count[lv] = level_vertex_count[lv] - 1
    end
  end
  nodecnt = 0
  for i = 1, sub_graph_size do
    local v = sub_graph_v[i]
    if sub_graph_v[v] then
      nodecnt = nodecnt + 1
      sub_graph_v[nodecnt] = v
    end
  end
  self.sub_graph_size = nodecnt
end

MPM.partialwork = function(self)
  local sum = 0
  while(self:subGraphConnected()) do
    local weak_vertex, potential = self:findWeakVertex()
    self:flowToT(weak_vertex, potential)
    self:flowFromS(weak_vertex, potential)
    self:updateSubGraph()
    sum = sum + potential
  end
  return sum
end

MPM.getMaxFlow = function(self)
  local ret = 0
  while(self:makeSubGraph()) do
    ret = ret + self:partialwork()
  end
  return ret
end

local AvlTree = {}
AvlTree.makenode = function(self, val, parent)
  local i = self.box[#self.box]
  if not i then i = #self.v + 1
  else table.remove(self.box)
  end
  self.v[i], self.p[i] = val, parent
  self.lc[i], self.rc[i], self.l[i], self.r[i] = 0, 0, 1, 1
  return i
end
AvlTree.create = function(self, lessthan, n)
  self.lessthan = lessthan
  self.root = 1
  self.box = {}
  for i = n + 1, 2, -1 do table.insert(self.box, i) end
  -- value, leftCount, rightCount, left, right, parent
  self.v, self.lc, self.rc, self.l, self.r, self.p = {}, {}, {}, {}, {}, {}
  for i = 1, n + 1 do
    self.v[i], self.p[i] = 0, 1
    self.lc[i], self.rc[i], self.l[i], self.r[i] = 0, 0, 1, 1
  end
end

AvlTree.recalc = function(self, i)
  local kl, kr = self.l[i], self.r[i]
  if 1 < kl then self.lc[i] = 1 + mma(self.lc[kl], self.rc[kl])
  else self.lc[i] = 0
  end
  if 1 < kr then self.rc[i] = 1 + mma(self.lc[kr], self.rc[kr])
  else self.rc[i] = 0
  end
end
AvlTree.recalcAll = function(self, i)
  while 1 < i do
    self:recalc(i)
    i = self.p[i]
  end
end

AvlTree.rotR = function(self, parent)
  local granp, child = self.p[parent], self.l[parent]
  self.r[child], self.l[parent] = parent, self.r[child]
  self.p[child], self.p[parent] = granp, child
  self.p[self.l[parent]] = parent
  if 1 < granp then
    if self.l[granp] == parent then
      self.l[granp] = child
    else
      self.r[granp] = child
    end
  else
    self.root = child
  end
end

AvlTree.rotL = function(self, parent)
  local granp, child = self.p[parent], self.r[parent]
  self.l[child], self.r[parent] = parent, self.l[child]
  self.p[child], self.p[parent] = granp, child
  self.p[self.r[parent]] = parent
  if 1 < granp then
    if self.r[granp] == parent then
      self.r[granp] = child
    else
      self.l[granp] = child
    end
  else
    self.root = child
  end
end

AvlTree.rotLR = function(self, lparent, rparent)
  local sp, sl, sr = self.p, self.l, self.r
  local granp, d = sp[rparent], sr[lparent]
  sp[lparent], sr[lparent] = d, sl[d]
  sp[rparent], sl[rparent] = d, sr[d]
  sp[sl[d]], sp[sr[d]] = lparent, rparent
  sp[d], sl[d], sr[d] = granp, lparent, rparent
  if 1 < granp then
    if sr[granp] == rparent then sr[granp] = d
    else sl[granp] = d
    end
  else self.root = d
  end
end

AvlTree.rotRL = function(self, rparent, lparent)
  local sp, sl, sr = self.p, self.l, self.r
  local granp, d = sp[lparent], sl[rparent]
  sp[rparent], sl[rparent] = d, sr[d]
  sp[lparent], sr[lparent] = d, sl[d]
  sp[sr[d]], sp[sl[d]] = rparent, lparent
  sp[d], sr[d], sl[d] = granp, rparent, lparent
  if 1 < granp then
    if sl[granp] == lparent then sl[granp] = d
    else sr[granp] = d
    end
  else self.root = d
  end
end

AvlTree.empty = function(self) return self.root <= 1 end

AvlTree.push = function(self, val)
  if self.root <= 1 then self.root = self:makenode(val, 1) return end
  local pos = self.root
  while true do
    if self.lessthan(val, self.v[pos]) then
      if 1 < self.l[pos] then
        pos = self.l[pos]
      else
        self.l[pos] = self:makenode(val, pos)
        pos = self.l[pos]
        break
      end
    else
      if 1 < self.r[pos] then
        pos = self.r[pos]
      else
        self.r[pos] = self:makenode(val, pos)
        pos = self.r[pos]
        break
      end
    end
  end
  while 1 < pos do
    local child, parent = pos, self.p[pos]
    if parent <= 1 then
      break
    end
    self:recalc(parent)
    local lcp_m_rcp = self.lc[parent] - self.rc[parent]
    if lcp_m_rcp % 2 ~= 0 then -- 1 or -1
      pos = parent
    elseif lcp_m_rcp == 2 then
      if self.lc[child] - 1 == self.rc[child] then
        self:rotR(parent)
        self:recalcAll(parent)
      else
        self:rotLR(child, parent)
        self:recalc(child)
        self:recalcAll(parent)
      end
      break
    elseif lcp_m_rcp == -2 then
      if self.rc[child] - 1 == self.lc[child] then
        self:rotL(parent)
        self:recalcAll(parent)
      else
        self:rotRL(child, parent)
        self:recalc(child)
        self:recalcAll(parent)
      end
      break
    else
      break
    end
  end
end

AvlTree.rmsub = function(self, node)
  while 1 < node do
    self:recalc(node)
    if self.lc[node] == self.rc[node] then
      node = self.p[node]
    elseif self.lc[node] + 1 == self.rc[node] then
      self:recalcAll(self.p[node])
      break
    else
      if self.lc[self.r[node]] == self.rc[self.r[node]] then
        self:rotL(node)
        self:recalcAll(node)
        break
      elseif self.lc[self.r[node]] + 1 == self.rc[self.r[node]] then
        local nr = self.r[node]
        self:rotL(node)
        self:recalc(node)
        node = nr
      else
        local nr = self.r[node]
        local nrl = self.l[nr]
        self:rotRL(nr, node)
        self:recalc(nr)
        self:recalc(node)
        node = nrl
      end
    end
  end
end

AvlTree.pop = function(self)
  local node = self.root
  while 1 < self.l[node] do
    node = self.l[node]
  end
  local v = self.v[node]
  local kp = self.p[node]
  self.p[self.r[node]] = kp
  if 1 < kp then
    self.l[kp] = self.r[node]
    self:rmsub(kp)
  else
    self.root = self.r[node]
  end
  table.insert(self.box, node)
  return v
end

AvlTree.new = function(lessthan, n)
  local obj = {}
  setmetatable(obj, {__index = AvlTree})
  obj:create(lessthan, n)
  return obj
end

local n, m = io.read("*n", "*n")
local ls, rs = {}, {}
local used = {}
local r_list = {}
local l_list = {}
for i = 1, m do
  r_list[i] = {}
  l_list[i] = {}
end
for i = 1, n do
  ls[i], rs[i] = io.read("*n", "*n")
  used[i] = false
  if rs[i] <= m then
    table.insert(r_list[rs[i]], i)
  end
  if 0 < ls[i] then
    table.insert(l_list[ls[i]], i)
  end
end
local function small_l_is_fast(a, b)
  return ls[a] < ls[b]
end
local avl1 = AvlTree.new(small_l_is_fast, 1)
local sit = 0
local chair_used = {}
for i = 1, m do
  for j = 1, #r_list[i] do
    avl1:push(r_list[i][j])
  end
  if not avl1:empty() then
    local top = avl1:pop()
    sit = sit + 1
    used[top] = i
    chair_used[i] = 1
  else
    chair_used[i] = false
  end
end
local rems = {}
for i = m, 1, -1 do
  for j = 1, #l_list[i] do
    local v = l_list[i][j]
    if not used[v] then
      table.insert(rems, v)
    end
  end
  if 0 < #rems and not chair_used[i] then
    used[rems[#rems]] = m + i
    sit = sit + 1
    chair_used[i] = 2
    table.remove(rems)
  end
end
-- print(n - sit)

local spos = n + m * 3 + 1
local tpos = spos + 1
MPM:initialize(tpos, spos, tpos)
for i = 1, n do
  local v = used[i]
  if v then
    if v <= m then
      if 0 < ls[i] then MPM:addEdge(i, n + m + ls[i], 1) end
      -- inv
      if rs[i] <= m then MPM:addEdge(n + rs[i], i, 1) end
    else
      if rs[i] <= m then MPM:addEdge(i, n + rs[i], 1) end
      -- inv
      if 0 < ls[i] then MPM:addEdge(n + m + ls[i], i, 1) end
    end
  else
    MPM:addEdge(spos, i, 1)
    if 0 < ls[i] then MPM:addEdge(i, n + m + ls[i], 1) end
    if rs[i] <= m then MPM:addEdge(i, n + rs[i], 1) end
  end
end
local inf = 1000000007
for i = 1, m - 1 do
  MPM:addEdge(n + i, n + i + 1, inf)
  MPM:addEdge(n + m + i + 1, n + m + i, inf)
end
for i = 1, m do
  local v = chair_used[i]
  if v == 1 then
    MPM:addEdge(n + m * 2 + i, n + i, 1)
    MPM:addEdge(n + m + i, n + m * 2 + i, 1)
  elseif v == 2 then
    MPM:addEdge(n + i, n + m * 2 + i, 1)
    MPM:addEdge(n + m * 2 + i, n + m + i, 1)
  else
    MPM:addEdge(n + i, n + m * 2 + i, 1)
    MPM:addEdge(n + m + i, n + m * 2 + i, 1)
    MPM:addEdge(n + m * 2 + i, tpos, 1)
  end
end
sit = sit + MPM:getMaxFlow()
print(n - sit)