The only difference between easy and hard versions is constraints.

You are given $n$ segments on the coordinate axis $OX$. Segments can intersect, lie inside each other and even coincide. The $i$-th segment is $[l_i; r_i]$ ($l_i \le r_i$) and it covers all integer points $j$ such that $l_i \le j \le r_i$.

The integer point is called bad if it is covered by strictly more than $k$ segments.

Your task is to remove the minimum number of segments so that there are no bad points at all.


-----Input-----

The first line of the input contains two integers $n$ and $k$ ($1 \le k \le n \le 2 \cdot 10^5$) — the number of segments and the maximum number of segments by which each integer point can be covered.

The next $n$ lines contain segments. The $i$-th line contains two integers $l_i$ and $r_i$ ($1 \le l_i \le r_i \le 2 \cdot 10^5$) — the endpoints of the $i$-th segment.


-----Output-----

In the first line print one integer $m$ ($0 \le m \le n$) — the minimum number of segments you need to remove so that there are no bad points.

In the second line print $m$ distinct integers $p_1, p_2, \dots, p_m$ ($1 \le p_i \le n$) — indices of segments you remove in any order. If there are multiple answers, you can print any of them.


-----Examples-----
Input
7 2
11 11
9 11
7 8
8 9
7 8
9 11
7 9

Output
3
4 6 7 

Input
5 1
29 30
30 30
29 29
28 30
30 30

Output
3
1 4 5 

Input
6 1
2 3
3 3
2 3
2 2
2 3
2 3

Output
4
1 3 5 6

Difficulty: MEDIUM_HARD
Tags: Sorting

Data structures

Greedy algorithms
Skill types: Sorting

Data structures

Greedy algorithms

Starter code:

Solutions:
import sys, heapq
mmx = 200000
ftree = [0] * (mmx + 1)

def uu(i, j, v):
	while i <= mmx:
		ftree[i] += v
		i += i & -i
	j += 1
	while j <= mmx:
		ftree[j] -= v
		j += j & -j

def qq(j):
	s = 0
	while j > 0:
		s += ftree[j]
		j -= j & -j
	return s
(n, k) = [int(i) for i in sys.stdin.readline().split()]
lns = sys.stdin.readlines()
bds = []
for j in range(n):
	t = [int(i) for i in lns[j].split()]
	t.append(j + 1)
	bds.append(t)
	uu(bds[-1][0], bds[-1][1], 1)
bds.sort()
bind = 0
heap = []
ans = []
for i in range(1, mmx + 1):
	while bind < n and bds[bind][0] == i:
		heapq.heappush(heap, (-1 * bds[bind][1], bds[bind][2]))
		bind += 1
	while qq(i) > k:
		(bd, bnd) = heapq.heappop(heap)
		ans.append(str(bnd))
		uu(i, -1 * bd, -1)
print(len(ans))
print(' '.join(ans))


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
import heapq as h
from collections import defaultdict
(n, ma) = map(int, input().split())
d = defaultdict(lambda : [])
he = []
dd = defaultdict(lambda : [])
for i in range(n):
	(l, r) = map(int, input().split())
	dd[r].append(i + 1)
	d[l].append([r, i + 1])
l = []
vis = [0] * (2 * 10 ** 5 + 2)
active = 0
for i in range(1, 2 * 10 ** 5 + 1):
	for k in d[i]:
		active += 1
		h.heappush(he, [-k[0], k[1]])
	while active > ma:
		var = h.heappop(he)
		while vis[var[1]] == 1:
			var = h.heappop(he)
		vis[var[1]] = 1
		l.append(var[1])
		active -= 1
	for j in dd[i]:
		if vis[j] == 0:
			vis[j] = 1
			active -= 1
print(len(l))
print(*l)


import sys, math, itertools
from collections import Counter, deque, defaultdict
from bisect import bisect_left, bisect_right
from heapq import heappop, heappush, heapify, nlargest
from copy import deepcopy
mod = 10 ** 9 + 7
INF = float('inf')

def inp():
	return int(sys.stdin.readline())

def inpl():
	return list(map(int, sys.stdin.readline().split()))

def inpl_1():
	return list(map(lambda x: int(x) - 1, sys.stdin.readline().split()))

def inps():
	return sys.stdin.readline()

def inpsl(x):
	tmp = sys.stdin.readline()
	return list(tmp[:x])

def err(x):
	print(x)
	exit()

def segfunc(x, y):
	return x + y

class LazySegTree_RAQ:

	def __init__(self, init_val, segfunc, ide_ele):
		n = len(init_val)
		self.segfunc = segfunc
		self.ide_ele = ide_ele
		self.num = 1 << (n - 1).bit_length()
		self.tree = [ide_ele] * 2 * self.num
		self.lazy = [0] * 2 * self.num
		for i in range(n):
			self.tree[self.num + i] = init_val[i]
		for i in range(self.num - 1, 0, -1):
			self.tree[i] = self.segfunc(self.tree[2 * i], self.tree[2 * i + 1])

	def gindex(self, l, r):
		l += self.num
		r += self.num
		lm = l >> (l & -l).bit_length()
		rm = r >> (r & -r).bit_length()
		while r > l:
			if l <= lm:
				yield l
			if r <= rm:
				yield r
			r >>= 1
			l >>= 1
		while l:
			yield l
			l >>= 1

	def propagates(self, *ids):
		for i in reversed(ids):
			v = self.lazy[i]
			if v == 0:
				continue
			self.lazy[i] = 0
			self.lazy[2 * i] += v
			self.lazy[2 * i + 1] += v
			self.tree[2 * i] += v
			self.tree[2 * i + 1] += v

	def add(self, l, r, x):
		(*ids,) = self.gindex(l, r)
		l += self.num
		r += self.num
		while l < r:
			if l & 1:
				self.lazy[l] += x
				self.tree[l] += x
				l += 1
			if r & 1:
				self.lazy[r - 1] += x
				self.tree[r - 1] += x
			r >>= 1
			l >>= 1
		for i in ids:
			self.tree[i] = self.segfunc(self.tree[2 * i], self.tree[2 * i + 1]) + self.lazy[i]

	def query(self, l, r):
		(*ids,) = self.gindex(l, r)
		self.propagates(*ids)
		res = self.ide_ele
		l += self.num
		r += self.num
		while l < r:
			if l & 1:
				res = self.segfunc(res, self.tree[l])
				l += 1
			if r & 1:
				res = self.segfunc(res, self.tree[r - 1])
			l >>= 1
			r >>= 1
		return res
(n, k) = inpl()
segs = []
for i in range(n):
	(l, r) = inpl()
	segs.append((l, r, i + 1))
segs.sort(key=lambda x: x[1])
st = LazySegTree_RAQ([0] * 200010, max, -1)
res = []
for (l, r, i) in segs:
	if st.query(l, r + 1) < k:
		st.add(l, r + 1, 1)
	else:
		res.append(i)
print(len(res))
print(*res)


import sys
from heapq import *
(n, k) = map(int, input().split())
seg = []
for i in range(n):
	(l, r) = map(int, input().split())
	seg.append((l, r, i + 1))
seg.sort()
c = 0
res = []
i = 0
hmin = []
hmax = []
rem = set()
while i < n:
	(l, r, si) = seg[i]
	while i < n and seg[i][0] == l:
		(_, r, si) = seg[i]
		heappush(hmax, (-r, si))
		heappush(hmin, (r, si))
		i += 1
		c += 1
	while len(hmin) > 0 and hmin[0][0] < l:
		(mr, ind) = heappop(hmin)
		if ind not in rem:
			c -= 1
	while c > k:
		(mr, ind) = heappop(hmax)
		res.append(ind)
		rem.add(ind)
		c -= 1
print(len(res))
if len(res) > 0:
	print(' '.join(map(str, res)))


import sys

def input():
	return sys.stdin.readline().strip()

def list2d(a, b, c):
	return [[c] * b for i in range(a)]

def list3d(a, b, c, d):
	return [[[d] * c for j in range(b)] for i in range(a)]

def list4d(a, b, c, d, e):
	return [[[[e] * d for j in range(c)] for j in range(b)] for i in range(a)]

def ceil(x, y=1):
	return int(-(-x // y))

def INT():
	return int(input())

def MAP():
	return list(map(int, input().split()))

def LIST(N=None):
	return list(MAP()) if N is None else [INT() for i in range(N)]

def Yes():
	print('Yes')

def No():
	print('No')

def YES():
	print('YES')

def NO():
	print('NO')
sys.setrecursionlimit(10 ** 7)
INF = 10 ** 18
MOD = 10 ** 9 + 7

class SegTreeIndex:

	def __init__(self, n, func, init):
		self.n = n
		self.func = func
		self.init = init
		n2 = 1
		while n2 < n:
			n2 <<= 1
		self.n2 = n2
		self.tree = [self.init] * (n2 << 1)
		self.index = [self.init] * (n2 << 1)
		for i in range(n2):
			self.index[i + n2] = i
		for i in range(n2 - 1, -1, -1):
			self.index[i] = self.index[i * 2]

	def update(self, i, x):
		i += self.n2
		self.tree[i] = x
		while i > 1:
			(left, right) = (min(i, i ^ 1), max(i, i ^ 1))
			if self.func(self.tree[left], self.tree[right]) == self.tree[left]:
				self.tree[i >> 1] = self.tree[left]
				self.index[i >> 1] = self.index[left]
			else:
				self.tree[i >> 1] = self.tree[right]
				self.index[i >> 1] = self.index[right]
			i >>= 1

	def query(self, a, b):
		l = a + self.n2
		r = b + self.n2
		s = (self.init, -1)
		while l < r:
			if r & 1:
				r -= 1
				res = self.func(s[0], self.tree[r])
				if res == s[0]:
					pass
				else:
					s = (self.tree[r], self.index[r])
			if l & 1:
				res = self.func(self.tree[l], s[0])
				if res == self.tree[l]:
					s = (self.tree[l], self.index[l])
				else:
					pass
				l += 1
			l >>= 1
			r >>= 1
		return s
(N, K) = MAP()
MAX = 200007
LRs = [[] for i in range(MAX + 2)]
R = [0] * (N + 1)
for i in range(N):
	(l, r) = MAP()
	LRs[l].append(i + 1)
	LRs[r + 1].append(-(i + 1))
	R[i + 1] = r
sti = SegTreeIndex(N + 1, max, -INF)
segcnt = 0
ans = []
removed = set()
for i in range(1, MAX + 2):
	for idx in LRs[i]:
		if idx > 0:
			sti.update(idx, R[idx])
			segcnt += 1
		else:
			idx = abs(idx)
			if idx not in removed:
				sti.update(idx, -INF)
				segcnt -= 1
	while segcnt > K:
		(mx, idx) = sti.query(0, N + 1)
		sti.update(idx, -INF)
		ans.append(idx)
		removed.add(idx)
		segcnt -= 1
print(len(ans))
print(*ans)


import os
import sys
from io import BytesIO, IOBase

class SortedList:

	def __init__(self, iterable=None, _load=200):
		if iterable is None:
			iterable = []
		values = sorted(iterable)
		self._len = _len = len(values)
		self._load = _load
		self._lists = _lists = [values[i:i + _load] for i in range(0, _len, _load)]
		self._list_lens = [len(_list) for _list in _lists]
		self._mins = [_list[0] for _list in _lists]
		self._fen_tree = []
		self._rebuild = True

	def _fen_build(self):
		self._fen_tree[:] = self._list_lens
		_fen_tree = self._fen_tree
		for i in range(len(_fen_tree)):
			if i | i + 1 < len(_fen_tree):
				_fen_tree[i | i + 1] += _fen_tree[i]
		self._rebuild = False

	def _fen_update(self, index, value):
		if not self._rebuild:
			_fen_tree = self._fen_tree
			while index < len(_fen_tree):
				_fen_tree[index] += value
				index |= index + 1

	def _fen_query(self, end):
		if self._rebuild:
			self._fen_build()
		_fen_tree = self._fen_tree
		x = 0
		while end:
			x += _fen_tree[end - 1]
			end &= end - 1
		return x

	def _fen_findkth(self, k):
		_list_lens = self._list_lens
		if k < _list_lens[0]:
			return (0, k)
		if k >= self._len - _list_lens[-1]:
			return (len(_list_lens) - 1, k + _list_lens[-1] - self._len)
		if self._rebuild:
			self._fen_build()
		_fen_tree = self._fen_tree
		idx = -1
		for d in reversed(range(len(_fen_tree).bit_length())):
			right_idx = idx + (1 << d)
			if right_idx < len(_fen_tree) and k >= _fen_tree[right_idx]:
				idx = right_idx
				k -= _fen_tree[idx]
		return (idx + 1, k)

	def _delete(self, pos, idx):
		_lists = self._lists
		_mins = self._mins
		_list_lens = self._list_lens
		self._len -= 1
		self._fen_update(pos, -1)
		del _lists[pos][idx]
		_list_lens[pos] -= 1
		if _list_lens[pos]:
			_mins[pos] = _lists[pos][0]
		else:
			del _lists[pos]
			del _list_lens[pos]
			del _mins[pos]
			self._rebuild = True

	def _loc_left(self, value):
		if not self._len:
			return (0, 0)
		_lists = self._lists
		_mins = self._mins
		(lo, pos) = (-1, len(_lists) - 1)
		while lo + 1 < pos:
			mi = lo + pos >> 1
			if value <= _mins[mi]:
				pos = mi
			else:
				lo = mi
		if pos and value <= _lists[pos - 1][-1]:
			pos -= 1
		_list = _lists[pos]
		(lo, idx) = (-1, len(_list))
		while lo + 1 < idx:
			mi = lo + idx >> 1
			if value <= _list[mi]:
				idx = mi
			else:
				lo = mi
		return (pos, idx)

	def _loc_right(self, value):
		if not self._len:
			return (0, 0)
		_lists = self._lists
		_mins = self._mins
		(pos, hi) = (0, len(_lists))
		while pos + 1 < hi:
			mi = pos + hi >> 1
			if value < _mins[mi]:
				hi = mi
			else:
				pos = mi
		_list = _lists[pos]
		(lo, idx) = (-1, len(_list))
		while lo + 1 < idx:
			mi = lo + idx >> 1
			if value < _list[mi]:
				idx = mi
			else:
				lo = mi
		return (pos, idx)

	def add(self, value):
		_load = self._load
		_lists = self._lists
		_mins = self._mins
		_list_lens = self._list_lens
		self._len += 1
		if _lists:
			(pos, idx) = self._loc_right(value)
			self._fen_update(pos, 1)
			_list = _lists[pos]
			_list.insert(idx, value)
			_list_lens[pos] += 1
			_mins[pos] = _list[0]
			if _load + _load < len(_list):
				_lists.insert(pos + 1, _list[_load:])
				_list_lens.insert(pos + 1, len(_list) - _load)
				_mins.insert(pos + 1, _list[_load])
				_list_lens[pos] = _load
				del _list[_load:]
				self._rebuild = True
		else:
			_lists.append([value])
			_mins.append(value)
			_list_lens.append(1)
			self._rebuild = True

	def discard(self, value):
		_lists = self._lists
		if _lists:
			(pos, idx) = self._loc_right(value)
			if idx and _lists[pos][idx - 1] == value:
				self._delete(pos, idx - 1)

	def remove(self, value):
		_len = self._len
		self.discard(value)
		if _len == self._len:
			raise ValueError('{0!r} not in list'.format(value))

	def pop(self, index=-1):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		value = self._lists[pos][idx]
		self._delete(pos, idx)
		return value

	def bisect_left(self, value):
		(pos, idx) = self._loc_left(value)
		return self._fen_query(pos) + idx

	def bisect_right(self, value):
		(pos, idx) = self._loc_right(value)
		return self._fen_query(pos) + idx

	def count(self, value):
		return self.bisect_right(value) - self.bisect_left(value)

	def __len__(self):
		return self._len

	def __getitem__(self, index):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		return self._lists[pos][idx]

	def __delitem__(self, index):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		self._delete(pos, idx)

	def __contains__(self, value):
		_lists = self._lists
		if _lists:
			(pos, idx) = self._loc_left(value)
			return idx < len(_lists[pos]) and _lists[pos][idx] == value
		return False

	def __iter__(self):
		return (value for _list in self._lists for value in _list)

	def __reversed__(self):
		return (value for _list in reversed(self._lists) for value in reversed(_list))

	def __repr__(self):
		return 'SortedList({0})'.format(list(self))

def main():
	(n, k) = map(int, input().split())
	(a, ma) = ([], 0)
	for i in range(n):
		(l, r) = map(int, input().split())
		a.append((l, r, i))
		ma = max(ma, r)
	a.sort(key=lambda x: x[0])
	(b, d) = ([0] * (ma + 2), SortedList())
	for i in a:
		b[i[0]] += 1
		b[i[1] + 1] -= 1
	for i in range(1, ma + 2):
		b[i] += b[i - 1]
	(ans, c, j) = ([], [0] * (ma + 2), 0)
	for i in range(1, ma + 1):
		c[i] += c[i - 1]
		if c[i] + b[i] > k:
			while j < n and a[j][0] <= i:
				d.add((a[j][1], a[j][0], a[j][2]))
				j += 1
			while d and d[0][0] < i:
				d.discard(d[0])
			z = c[i] + b[i] - k
			c[i] -= z
			while z:
				y = d[-1]
				d.discard(d[-1])
				c[y[0] + 1] += 1
				ans.append(y[-1] + 1)
				z -= 1
	print(len(ans))
	print(*ans)
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
main()


import sys
from heapq import *
(n, k) = map(int, input().split())
N = int(200000.0 + 2)
ll = [[] for _ in range(N)]
rr = [[] for _ in range(N)]
vis = [0] * N
for i in range(n):
	(l, r) = map(int, sys.stdin.readline().split())
	ll[l].append((-r, i + 1))
	rr[r].append(i + 1)
q = []
ans = []
size = 0
for i in range(1, N):
	for j in ll[i]:
		heappush(q, j)
		size += 1
	while size > k:
		cur = heappop(q)
		vis[cur[1]] = 1
		ans.append(cur[1])
		size -= 1
	for j in rr[i]:
		if not vis[j]:
			vis[j] = 1
			size -= 1
print(len(ans))
print(*ans)


import os
import sys
from io import BytesIO, IOBase
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')
import heapq

def main():
	(n, k) = map(int, input().split())
	segs = []
	dict1 = {}
	nums = 2 * 10 ** 5
	for s in range(n):
		(l, r) = map(int, input().split())
		segs.append((l, r, s + 1))
	segs.sort(key=lambda x: [x[0], x[1]])
	for s in range(n - 1, -1, -1):
		if not segs[s][1] in dict1:
			dict1[segs[s][1]] = [segs[s][2]]
		else:
			dict1[segs[s][1]].append(segs[s][2])
	heapy = []
	mark = [0 for s in range(nums + 2)]
	cv = 0
	tt = 0
	ans = []
	for point in range(1, nums + 1):
		while cv < n and segs[cv][0] <= point:
			heapq.heappush(heapy, -segs[cv][1])
			mark[segs[cv][1]] += 1
			cv += 1
		while len(heapy) > 0 and len(heapy) - tt > k:
			v0 = -heapq.heappop(heapy)
			if v0 >= point:
				ans.append(dict1[v0].pop())
				mark[v0] -= 1
			else:
				tt -= 1
				mark[v0] -= 1
		tt += mark[point]
	print(len(ans))
	print(*ans)
main()


class SortedList:

	def __init__(self, iterable=[], _load=200):
		values = sorted(iterable)
		self._len = _len = len(values)
		self._load = _load
		self._lists = _lists = [values[i:i + _load] for i in range(0, _len, _load)]
		self._list_lens = [len(_list) for _list in _lists]
		self._mins = [_list[0] for _list in _lists]
		self._fen_tree = []
		self._rebuild = True

	def _fen_build(self):
		self._fen_tree[:] = self._list_lens
		_fen_tree = self._fen_tree
		for i in range(len(_fen_tree)):
			if i | i + 1 < len(_fen_tree):
				_fen_tree[i | i + 1] += _fen_tree[i]
		self._rebuild = False

	def _fen_update(self, index, value):
		if not self._rebuild:
			_fen_tree = self._fen_tree
			while index < len(_fen_tree):
				_fen_tree[index] += value
				index |= index + 1

	def _fen_query(self, end):
		if self._rebuild:
			self._fen_build()
		_fen_tree = self._fen_tree
		x = 0
		while end:
			x += _fen_tree[end - 1]
			end &= end - 1
		return x

	def _fen_findkth(self, k):
		_list_lens = self._list_lens
		if k < _list_lens[0]:
			return (0, k)
		if k >= self._len - _list_lens[-1]:
			return (len(_list_lens) - 1, k + _list_lens[-1] - self._len)
		if self._rebuild:
			self._fen_build()
		_fen_tree = self._fen_tree
		idx = -1
		for d in reversed(range(len(_fen_tree).bit_length())):
			right_idx = idx + (1 << d)
			if right_idx < len(_fen_tree) and k >= _fen_tree[right_idx]:
				idx = right_idx
				k -= _fen_tree[idx]
		return (idx + 1, k)

	def _delete(self, pos, idx):
		_lists = self._lists
		_mins = self._mins
		_list_lens = self._list_lens
		self._len -= 1
		self._fen_update(pos, -1)
		del _lists[pos][idx]
		_list_lens[pos] -= 1
		if _list_lens[pos]:
			_mins[pos] = _lists[pos][0]
		else:
			del _lists[pos]
			del _list_lens[pos]
			del _mins[pos]
			self._rebuild = True

	def _loc_left(self, value):
		if not self._len:
			return (0, 0)
		_lists = self._lists
		_mins = self._mins
		(lo, pos) = (-1, len(_lists) - 1)
		while lo + 1 < pos:
			mi = lo + pos >> 1
			if value <= _mins[mi]:
				pos = mi
			else:
				lo = mi
		if pos and value <= _lists[pos - 1][-1]:
			pos -= 1
		_list = _lists[pos]
		(lo, idx) = (-1, len(_list))
		while lo + 1 < idx:
			mi = lo + idx >> 1
			if value <= _list[mi]:
				idx = mi
			else:
				lo = mi
		return (pos, idx)

	def _loc_right(self, value):
		if not self._len:
			return (0, 0)
		_lists = self._lists
		_mins = self._mins
		(pos, hi) = (0, len(_lists))
		while pos + 1 < hi:
			mi = pos + hi >> 1
			if value < _mins[mi]:
				hi = mi
			else:
				pos = mi
		_list = _lists[pos]
		(lo, idx) = (-1, len(_list))
		while lo + 1 < idx:
			mi = lo + idx >> 1
			if value < _list[mi]:
				idx = mi
			else:
				lo = mi
		return (pos, idx)

	def add(self, value):
		_load = self._load
		_lists = self._lists
		_mins = self._mins
		_list_lens = self._list_lens
		self._len += 1
		if _lists:
			(pos, idx) = self._loc_right(value)
			self._fen_update(pos, 1)
			_list = _lists[pos]
			_list.insert(idx, value)
			_list_lens[pos] += 1
			_mins[pos] = _list[0]
			if _load + _load < len(_list):
				_lists.insert(pos + 1, _list[_load:])
				_list_lens.insert(pos + 1, len(_list) - _load)
				_mins.insert(pos + 1, _list[_load])
				_list_lens[pos] = _load
				del _list[_load:]
				self._rebuild = True
		else:
			_lists.append([value])
			_mins.append(value)
			_list_lens.append(1)
			self._rebuild = True

	def discard(self, value):
		_lists = self._lists
		if _lists:
			(pos, idx) = self._loc_right(value)
			if idx and _lists[pos][idx - 1] == value:
				self._delete(pos, idx - 1)

	def remove(self, value):
		_len = self._len
		self.discard(value)
		if _len == self._len:
			raise ValueError('{0!r} not in list'.format(value))

	def pop(self, index=-1):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		value = self._lists[pos][idx]
		self._delete(pos, idx)
		return value

	def bisect_left(self, value):
		(pos, idx) = self._loc_left(value)
		return self._fen_query(pos) + idx

	def bisect_right(self, value):
		(pos, idx) = self._loc_right(value)
		return self._fen_query(pos) + idx

	def count(self, value):
		return self.bisect_right(value) - self.bisect_left(value)

	def __len__(self):
		return self._len

	def __getitem__(self, index):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		return self._lists[pos][idx]

	def __delitem__(self, index):
		(pos, idx) = self._fen_findkth(self._len + index if index < 0 else index)
		self._delete(pos, idx)

	def __contains__(self, value):
		_lists = self._lists
		if _lists:
			(pos, idx) = self._loc_left(value)
			return idx < len(_lists[pos]) and _lists[pos][idx] == value
		return False

	def __iter__(self):
		return (value for _list in self._lists for value in _list)

	def __reversed__(self):
		return (value for _list in reversed(self._lists) for value in reversed(_list))

	def __repr__(self):
		return 'SortedList({0})'.format(list(self))

class OrderedList(SortedList):

	def __init__(self, arg):
		super().__init__(arg)

	def rangeCountByValue(self, leftVal, rightVal):
		leftCummulative = self.bisect_left(leftVal)
		rightCummulative = self.bisect_left(rightVal + 1)
		return rightCummulative - leftCummulative

def main():
	(n, k) = readIntArr()
	lr = []
	for i in range(n):
		(l, r) = readIntArr()
		lr.append([l, r, i + 1])
	lr.sort(key=lambda x: x[0])
	storedRandI = OrderedList([])
	ans = []
	cnts = 0
	for (l, r, i) in lr:
		while storedRandI and storedRandI[0][0] < l:
			storedRandI.pop(0)
			cnts -= 1
		storedRandI.add([r, i])
		cnts += 1
		while cnts > k:
			(r, i) = storedRandI.pop(-1)
			cnts -= 1
			ans.append(i)
	print(len(ans))
	oneLineArrayPrint(ans)
	return
import sys
input = sys.stdin.buffer.readline

def oneLineArrayPrint(arr):
	print(' '.join([str(x) for x in arr]))

def multiLineArrayPrint(arr):
	print('\n'.join([str(x) for x in arr]))

def multiLineArrayOfArraysPrint(arr):
	print('\n'.join([' '.join([str(x) for x in y]) for y in arr]))

def readIntArr():
	return [int(x) for x in input().split()]

def makeArr(defaultVal, dimensionArr):
	dv = defaultVal
	da = dimensionArr
	if len(da) == 1:
		return [dv for _ in range(da[0])]
	else:
		return [makeArr(dv, da[1:]) for _ in range(da[0])]

def queryInteractive(x, y):
	print('? {} {}'.format(x, y))
	sys.stdout.flush()
	return int(input())

def answerInteractive(ans):
	print('! {}'.format(ans))
	sys.stdout.flush()
inf = float('inf')
MOD = 10 ** 9 + 7
for _abc in range(1):
	main()


from operator import itemgetter
import sys
input = sys.stdin.readline
(n, m) = map(int, input().split())
info = [list(map(int, input().split())) + [i] for i in range(n)]
info = sorted(info, key=itemgetter(1))
max_num = info[-1][1]
N = max_num
INF = 0
LV = (N - 1).bit_length()
N0 = 2 ** LV
data = [0] * (2 * N0)
lazy = [0] * (2 * N0)

def gindex(l, r):
	L = l + N0 >> 1
	R = r + N0 >> 1
	lc = 0 if l & 1 else (L & -L).bit_length()
	rc = 0 if r & 1 else (R & -R).bit_length()
	for i in range(LV):
		if rc <= i:
			yield R
		if L < R and lc <= i:
			yield L
		L >>= 1
		R >>= 1

def propagates(*ids):
	for i in reversed(ids):
		v = lazy[i - 1]
		if not v:
			continue
		lazy[2 * i - 1] += v
		lazy[2 * i] += v
		data[2 * i - 1] += v
		data[2 * i] += v
		lazy[i - 1] = 0

def update(l, r, x):
	(*ids,) = gindex(l, r)
	propagates(*ids)
	L = N0 + l
	R = N0 + r
	while L < R:
		if R & 1:
			R -= 1
			lazy[R - 1] += x
			data[R - 1] += x
		if L & 1:
			lazy[L - 1] += x
			data[L - 1] += x
			L += 1
		L >>= 1
		R >>= 1
	for i in ids:
		data[i - 1] = max(data[2 * i - 1], data[2 * i])

def query(l, r):
	propagates(*gindex(l, r))
	L = N0 + l
	R = N0 + r
	s = INF
	while L < R:
		if R & 1:
			R -= 1
			s = max(s, data[R - 1])
		if L & 1:
			s = max(s, data[L - 1])
			L += 1
		L >>= 1
		R >>= 1
	return s
ans = []
for i in range(n):
	(l, r, j) = info[i]
	r += 1
	if query(l, r) < m:
		update(l, r, 1)
	else:
		ans.append(j + 1)
print(len(ans))
print(*ans)


import sys

def input():
	return sys.stdin.readline().strip()
import heapq
maxn = 200005

def lowbit(x):
	return x & -x

def add(t, i, v):
	while i < len(t):
		t[i] += v
		i += lowbit(i)

def sum(t, i):
	ans = 0
	while i > 0:
		ans += t[i]
		i -= lowbit(i)
	return ans
trees = [0] * maxn
(n, k) = map(int, input().split(' '))
seg = []
points = [0] * maxn
cand = []
for i in range(n):
	(l, r) = map(int, input().split(' '))
	seg.append((l, r, i + 1))
	points[l] += 1
	points[r + 1] -= 1
st = 0
for i in range(maxn):
	st += points[i]
	if st > k:
		cand.append((i, st - k))
seg.sort(key=lambda x: (x[0], x[1]))
pq = []
j = 0
ans = []
for (i, v) in cand:
	v = v - sum(trees, i)
	if v <= 0:
		continue
	while j < n and seg[j][0] <= i:
		heapq.heappush(pq, (-seg[j][1], seg[j][0], seg[j][2]))
		j += 1
	for t in range(v):
		(r, l, idx) = heapq.heappop(pq)
		ans.append(idx)
		add(trees, l, 1)
		add(trees, -r + 1, -1)
print(len(ans))
print(*ans)


import sys
reader = (s.rstrip() for s in sys.stdin)
input = reader.__next__
from heapq import heappop, heappush

class RangeAddQuery:

	def __init__(self, n):
		self.n0 = 2 ** (n - 1).bit_length()
		self.data = [0] * (2 * self.n0 - 1)

	def add(self, l, r, v):
		l += self.n0
		r += self.n0
		while l < r:
			if r & 1:
				r -= 1
				self.data[r - 1] += v
			if l & 1:
				self.data[l - 1] += v
				l += 1
			l >>= 1
			r >>= 1

	def query(self, i):
		i += self.n0 - 1
		res = 0
		while i + 1:
			if self.data[i]:
				res += self.data[i]
			i = ~-i // 2
		return res
(n, k) = list(map(int, input().split()))
m = 2 * 10 ** 5
RAQ = RangeAddQuery(m + 10)
segments = []
for i in range(n):
	(a, b) = list(map(int, input().split()))
	(a, b) = (a - 1, b - 1)
	RAQ.add(a, b + 1, 1)
	segments.append((a, b, i + 1))
segments.sort()
cursor = 0
heap = []
ans = []
for i in range(m):
	while cursor != n and segments[cursor][0] == i:
		heappush(heap, (-segments[cursor][1], segments[cursor][0], segments[cursor][2]))
		cursor += 1
	cnt = max(0, RAQ.query(i) - k)
	while cnt:
		(r, l, p) = heappop(heap)
		r = -r
		if r < i:
			continue
		RAQ.add(l, r + 1, -1)
		cnt -= 1
		ans.append(p)
print(len(ans))
print(*ans)


from heapq import *

def main():
	(n, k) = map(int, input().split())
	E = []
	opent = {}
	for i in range(n):
		(l, r) = map(int, input().split())
		E.append([l, 1, i])
		E.append([r, -1, i])
		opent[i] = r
	E.sort(key=lambda x: (x[0], -x[1]))
	now_r = []
	heapify(now_r)
	cnt_delet = 0
	ans = []
	deleted = set()
	for (x, t, i) in E:
		if t == 1:
			heappush(now_r, -(opent[i] * 10 ** 6 + i))
		elif i not in deleted:
			cnt_delet += 1
		if len(now_r) - cnt_delet > k:
			for _ in range(len(now_r) - cnt_delet - k):
				nm = heappop(now_r)
				ind = -nm % 10 ** 6
				ans.append(ind + 1)
				deleted.add(ind)
	print(len(ans))
	print(' '.join(list(map(str, ans))))
main()


import heapq
(n, k) = list(map(int, input().split()))
length = 2 * 10 ** 5
llist = [[] for x in range(length + 1)]
rlist = [[] for x in range(length + 1)]
flag = [0] * (length + 1)
for i in range(n):
	(l, r) = list(map(int, input().split()))
	llist[l].append([i + 1, r])
	rlist[r].append([i + 1, l])
heap = []
ans = []
now = 0
for i in range(length):
	i += 1
	for j in llist[i]:
		now += 1
		currents = j[0]
		r = j[1]
		flag[currents] = 1
		heapq.heappush(heap, [-1 * r, currents])
	for j in rlist[i - 1]:
		currents = j[0]
		if flag[currents] == 1:
			now -= 1
			flag[currents] = 0
	while now > k:
		removing = heapq.heappop(heap)
		currents = removing[1]
		if flag[currents] == 1:
			ans.append(currents)
			now -= 1
			flag[currents] = 0
print(len(ans))
print(' '.join(map(str, ans)))


import sys
input = sys.stdin.readline
(n, k) = map(int, input().split())
S = [tuple(map(int, input().split())) + (i + 1,) for i in range(n)]
S.sort()
segtemp = 2 * 10 ** 5
seg_el = 1 << segtemp.bit_length()
SEG = [0] * (2 * seg_el)

def getvalue(n, seg_el):
	i = n + seg_el
	ANS = 0
	ANS += SEG[i]
	i >>= 1
	while i != 0:
		ANS += SEG[i]
		i >>= 1
	return ANS

def updates(l, r, x):
	L = l + seg_el
	R = r + seg_el
	while L < R:
		if L & 1:
			SEG[L] += x
			L += 1
		if R & 1:
			R -= 1
			SEG[R] += x
		L >>= 1
		R >>= 1
ind = 0
SH = []
ANS = []
import heapq
for point in range(segtemp):
	while ind < n and S[ind][0] <= point:
		(l, r, x) = S[ind]
		updates(l, r + 1, 1)
		ind += 1
		heapq.heappush(SH, (-r, l, x))
	while getvalue(point, seg_el) > k:
		(r, l, x) = heapq.heappop(SH)
		r = -r
		ANS.append(x)
		updates(l, r + 1, -1)
print(len(ANS))
print(*ANS)


from sys import stdin
from sys import setrecursionlimit as SRL
SRL(10 ** 7)
rd = stdin.readline
rrd = lambda : map(int, rd().strip().split())
(n, k) = rrd()
ll = [[] for _i in range(200005)]
rr = [[] for _i in range(200005)]
for i in range(n):
	(l, r) = rrd()
	ll[l].append([-r, i + 1])
	rr[r].append(i + 1)
from heapq import *
q = []
lenth = 0
ans = []
vis = [0] * 200005
for i in range(1, 200005):
	for j in ll[i]:
		heappush(q, j)
		lenth += 1
	while lenth > k:
		now = heappop(q)
		while vis[now[1]]:
			now = heappop(q)
		vis[now[1]] = 1
		ans.append(now[1])
		lenth -= 1
	for j in rr[i]:
		if not vis[j]:
			vis[j] = 1
			lenth -= 1
print(len(ans))
print(' '.join(map(str, ans)))


from sys import stdin, stdout
from math import gcd, sqrt, factorial, pi, inf
from collections import deque, defaultdict
from bisect import bisect, bisect_left
from time import time
from itertools import permutations as per
from heapq import heapify, heappush, heappop, heappushpop
input = stdin.readline
R = lambda : map(int, input().split())
I = lambda : int(input())
S = lambda : input().rstrip('\r\n')
L = lambda : list(R())
P = lambda x: stdout.write(str(x) + '\n')
lcm = lambda x, y: x * y // gcd(x, y)
nCr = lambda x, y: f[x] * inv(f[y] * f[x - y] % N) % N
inv = lambda x: pow(x, N - 2, N)
sm = lambda x: (x ** 2 + x) // 2
N = 10 ** 9 + 7
(n, k) = R()
a = [0] * (2 * 10 ** 5 + 7)
v = [defaultdict(list) for i in range(2 * 10 ** 5 + 7)]
for i in range(n):
	(x, y) = R()
	a[y + 1] -= 1
	v[x][y] += (i + 1,)
p = 0
h = []
ans = []
ind = defaultdict(list)
for i in range(2 * 10 ** 5 + 7):
	p += a[i]
	for j in v[i]:
		for g in v[i][j]:
			ind[j] += (g,)
			if p < k:
				heappush(h, -j)
				p += 1
			else:
				x = -heappushpop(h, -j)
				ans += (ind[x].pop(),)
				a[x + 1] += 1
print(len(ans))
print(*ans)


import sys
import bisect
import heapq
line_count = 0
segments = [None]
num_points = 200000
for line in sys.stdin.readlines():
	inputs = line.split()
	if line_count == 0:
		n = int(inputs[0])
		k = int(inputs[1])
		opening = {}
		closing = {}
		removed_right = {}
		segment_index = 0
		for i in range(1, num_points + 1):
			opening[i] = []
			closing[i] = []
			removed_right[i] = 0
	else:
		l = int(inputs[0])
		r = int(inputs[1])
		segment_index += 1
		segments.append((l, r))
		opening[l].append(segment_index)
		closing[r].append(segment_index)
	if line_count == n:
		break
	line_count += 1
working = []
working_count = 0
removed = []
for i in range(1, num_points + 1):
	for segment_index in opening[i]:
		(_, r) = segments[segment_index]
		heapq.heappush(working, (-r, segment_index))
		working_count += 1
	while working_count > k:
		(r, segment_index) = heapq.heappop(working)
		working_count -= 1
		removed.append(segment_index)
		removed_right[-r] += 1
	squeezed_out = len(closing[i]) - removed_right[i]
	working_count -= squeezed_out
print(len(removed))
for j in removed:
	print(j, end=' ')


import heapq
(N, K) = [int(x) for x in input().split()]
L2RI = [[] for i in range(200000)]
for i in range(N):
	(l, r) = [int(x) for x in input().split()]
	L2RI[l - 1].append([-(r - 1), i + 1])
ans = []
que = []
heapq.heapify(que)
hist = [0] * 200000
exited = 0
for l in range(200000):
	for ri in L2RI[l]:
		heapq.heappush(que, ri)
		hist[-ri[0]] += 1
	while len(que) - exited > K:
		top = heapq.heappop(que)
		hist[-top[0]] -= 1
		ans.append(top[1])
	exited += hist[l]
print(len(ans))
print(*ans)


import math
import random
import heapq, bisect
import sys
from collections import deque, defaultdict
from fractions import Fraction
import sys
import threading
from collections import defaultdict
threading.stack_size(10 ** 8)
mod = 10 ** 9 + 7
mod1 = 998244353
import os
import sys
from io import BytesIO, IOBase
sys.setrecursionlimit(300000)
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		self._fd = file.fileno()
		self.buffer = BytesIO()
		self.writable = 'x' in file.mode or 'r' not in file.mode
		self.write = self.buffer.write if self.writable else None

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			if not b:
				break
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines = 0
		return self.buffer.read()

	def readline(self):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, BUFSIZE))
			self.newlines = b.count(b'\n') + (not b)
			ptr = self.buffer.tell()
			(self.buffer.seek(0, 2), self.buffer.write(b), self.buffer.seek(ptr))
		self.newlines -= 1
		return self.buffer.readline()

	def flush(self):
		if self.writable:
			os.write(self._fd, self.buffer.getvalue())
			(self.buffer.truncate(0), self.buffer.seek(0))

class IOWrapper(IOBase):

	def __init__(self, file):
		self.buffer = FastIO(file)
		self.flush = self.buffer.flush
		self.writable = self.buffer.writable
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')
(sys.stdin, sys.stdout) = (IOWrapper(sys.stdin), IOWrapper(sys.stdout))
input = lambda : sys.stdin.readline().rstrip('\r\n')

class TreeNode:

	def __init__(self, k, v):
		self.key = k
		self.value = v
		self.left = None
		self.right = None
		self.parent = None
		self.height = 1
		self.num_left = 1
		self.num_total = 1

class AvlTree:

	def __init__(self):
		self._tree = None

	def add(self, k, v):
		if not self._tree:
			self._tree = TreeNode(k, v)
			return
		node = self._add(k, v)
		if node:
			self._rebalance(node)

	def _add(self, k, v):
		node = self._tree
		while node:
			if k < node.key:
				if node.left:
					node = node.left
				else:
					node.left = TreeNode(k, v)
					node.left.parent = node
					return node.left
			elif node.key < k:
				if node.right:
					node = node.right
				else:
					node.right = TreeNode(k, v)
					node.right.parent = node
					return node.right
			else:
				node.value = v
				return

	@staticmethod
	def get_height(x):
		return x.height if x else 0

	@staticmethod
	def get_num_total(x):
		return x.num_total if x else 0

	def _rebalance(self, node):
		n = node
		while n:
			lh = self.get_height(n.left)
			rh = self.get_height(n.right)
			n.height = max(lh, rh) + 1
			balance_factor = lh - rh
			n.num_total = 1 + self.get_num_total(n.left) + self.get_num_total(n.right)
			n.num_left = 1 + self.get_num_total(n.left)
			if balance_factor > 1:
				if self.get_height(n.left.left) < self.get_height(n.left.right):
					self._rotate_left(n.left)
				self._rotate_right(n)
			elif balance_factor < -1:
				if self.get_height(n.right.right) < self.get_height(n.right.left):
					self._rotate_right(n.right)
				self._rotate_left(n)
			else:
				n = n.parent

	def _remove_one(self, node):
		replacement = node.left or node.right
		if node.parent:
			if AvlTree._is_left(node):
				node.parent.left = replacement
			else:
				node.parent.right = replacement
			replacement.parent = node.parent
			node.parent = None
		else:
			self._tree = replacement
			replacement.parent = None
		node.left = None
		node.right = None
		node.parent = None
		self._rebalance(replacement)

	def _remove_leaf(self, node):
		if node.parent:
			if AvlTree._is_left(node):
				node.parent.left = None
			else:
				node.parent.right = None
			self._rebalance(node.parent)
		else:
			self._tree = None
		node.parent = None
		node.left = None
		node.right = None

	def remove(self, k):
		node = self._get_node(k)
		if not node:
			return
		if AvlTree._is_leaf(node):
			self._remove_leaf(node)
			return
		if node.left and node.right:
			nxt = AvlTree._get_next(node)
			node.key = nxt.key
			node.value = nxt.value
			if self._is_leaf(nxt):
				self._remove_leaf(nxt)
			else:
				self._remove_one(nxt)
			self._rebalance(node)
		else:
			self._remove_one(node)

	def get(self, k):
		node = self._get_node(k)
		return node.value if node else -1

	def _get_node(self, k):
		if not self._tree:
			return None
		node = self._tree
		while node:
			if k < node.key:
				node = node.left
			elif node.key < k:
				node = node.right
			else:
				return node
		return None

	def get_at(self, pos):
		x = pos + 1
		node = self._tree
		while node:
			if x < node.num_left:
				node = node.left
			elif node.num_left < x:
				x -= node.num_left
				node = node.right
			else:
				return (node.key, node.value)
		raise IndexError('Out of ranges')

	@staticmethod
	def _is_left(node):
		return node.parent.left and node.parent.left == node

	@staticmethod
	def _is_leaf(node):
		return node.left is None and node.right is None

	def _rotate_right(self, node):
		if not node.parent:
			self._tree = node.left
			node.left.parent = None
		elif AvlTree._is_left(node):
			node.parent.left = node.left
			node.left.parent = node.parent
		else:
			node.parent.right = node.left
			node.left.parent = node.parent
		bk = node.left.right
		node.left.right = node
		node.parent = node.left
		node.left = bk
		if bk:
			bk.parent = node
		node.height = max(self.get_height(node.left), self.get_height(node.right)) + 1
		node.num_total = 1 + self.get_num_total(node.left) + self.get_num_total(node.right)
		node.num_left = 1 + self.get_num_total(node.left)

	def _rotate_left(self, node):
		if not node.parent:
			self._tree = node.right
			node.right.parent = None
		elif AvlTree._is_left(node):
			node.parent.left = node.right
			node.right.parent = node.parent
		else:
			node.parent.right = node.right
			node.right.parent = node.parent
		bk = node.right.left
		node.right.left = node
		node.parent = node.right
		node.right = bk
		if bk:
			bk.parent = node
		node.height = max(self.get_height(node.left), self.get_height(node.right)) + 1
		node.num_total = 1 + self.get_num_total(node.left) + self.get_num_total(node.right)
		node.num_left = 1 + self.get_num_total(node.left)

	@staticmethod
	def _get_next(node):
		if not node.right:
			return node.parent
		n = node.right
		while n.left:
			n = n.left
		return n

class SegmentTree1:

	def __init__(self, data, default=2 ** 51, func=lambda a, b: a & b):
		self._default = default
		self._func = func
		self._len = len(data)
		self._size = _size = 1 << (self._len - 1).bit_length()
		self.data = [default] * (2 * _size)
		self.data[_size:_size + self._len] = data
		for i in reversed(range(_size)):
			self.data[i] = func(self.data[i + i], self.data[i + i + 1])

	def __delitem__(self, idx):
		self[idx] = self._default

	def __getitem__(self, idx):
		return self.data[idx + self._size]

	def __setitem__(self, idx, value):
		idx += self._size
		self.data[idx] = value
		idx >>= 1
		while idx:
			self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
			idx >>= 1

	def __len__(self):
		return self._len

	def query(self, start, stop):
		if start == stop:
			return self.__getitem__(start)
		stop += 1
		start += self._size
		stop += self._size
		res = self._default
		while start < stop:
			if start & 1:
				res = self._func(res, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res = self._func(res, self.data[stop])
			start >>= 1
			stop >>= 1
		return res

	def __repr__(self):
		return 'SegmentTree({0})'.format(self.data)

class SegmentTree:

	def __init__(self, data, default=0, func=lambda a, b: a + b):
		self._default = default
		self._func = func
		self._len = len(data)
		self._size = _size = 1 << (self._len - 1).bit_length()
		self.data = [default] * (2 * _size)
		self.data[_size:_size + self._len] = data
		for i in reversed(range(_size)):
			self.data[i] = func(self.data[i + i], self.data[i + i + 1])

	def __delitem__(self, idx):
		self[idx] = self._default

	def __getitem__(self, idx):
		return self.data[idx + self._size]

	def __setitem__(self, idx, value):
		idx += self._size
		self.data[idx] = value
		idx >>= 1
		while idx:
			self.data[idx] = self._func(self.data[2 * idx], self.data[2 * idx + 1])
			idx >>= 1

	def __len__(self):
		return self._len

	def query(self, start, stop):
		if start == stop:
			return self.__getitem__(start)
		stop += 1
		start += self._size
		stop += self._size
		res = self._default
		while start < stop:
			if start & 1:
				res = self._func(res, self.data[start])
				start += 1
			if stop & 1:
				stop -= 1
				res = self._func(res, self.data[stop])
			start >>= 1
			stop >>= 1
		return res

	def __repr__(self):
		return 'SegmentTree({0})'.format(self.data)

class Factorial:

	def __init__(self, MOD):
		self.MOD = MOD
		self.factorials = [1, 1]
		self.invModulos = [0, 1]
		self.invFactorial_ = [1, 1]

	def calc(self, n):
		if n <= -1:
			print('Invalid argument to calculate n!')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		if n < len(self.factorials):
			return self.factorials[n]
		nextArr = [0] * (n + 1 - len(self.factorials))
		initialI = len(self.factorials)
		prev = self.factorials[-1]
		m = self.MOD
		for i in range(initialI, n + 1):
			prev = nextArr[i - initialI] = prev * i % m
		self.factorials += nextArr
		return self.factorials[n]

	def inv(self, n):
		if n <= -1:
			print('Invalid argument to calculate n^(-1)')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		p = self.MOD
		pi = n % p
		if pi < len(self.invModulos):
			return self.invModulos[pi]
		nextArr = [0] * (n + 1 - len(self.invModulos))
		initialI = len(self.invModulos)
		for i in range(initialI, min(p, n + 1)):
			next = -self.invModulos[p % i] * (p // i) % p
			self.invModulos.append(next)
		return self.invModulos[pi]

	def invFactorial(self, n):
		if n <= -1:
			print('Invalid argument to calculate (n^(-1))!')
			print('n must be non-negative value. But the argument was ' + str(n))
			exit()
		if n < len(self.invFactorial_):
			return self.invFactorial_[n]
		self.inv(n)
		nextArr = [0] * (n + 1 - len(self.invFactorial_))
		initialI = len(self.invFactorial_)
		prev = self.invFactorial_[-1]
		p = self.MOD
		for i in range(initialI, n + 1):
			prev = nextArr[i - initialI] = prev * self.invModulos[i % p] % p
		self.invFactorial_ += nextArr
		return self.invFactorial_[n]

class Combination:

	def __init__(self, MOD):
		self.MOD = MOD
		self.factorial = Factorial(MOD)

	def ncr(self, n, k):
		if k < 0 or n < k:
			return 0
		k = min(k, n - k)
		f = self.factorial
		return f.calc(n) * f.invFactorial(max(n - k, k)) * f.invFactorial(min(k, n - k)) % self.MOD

def powm(a, n, m):
	if a == 1 or n == 0:
		return 1
	if n % 2 == 0:
		s = powm(a, n // 2, m)
		return s * s % m
	else:
		return a * powm(a, n - 1, m) % m

def sort_list(list1, list2):
	zipped_pairs = zip(list2, list1)
	z = [x for (_, x) in sorted(zipped_pairs)]
	return z

def product(l):
	por = 1
	for i in range(len(l)):
		por *= l[i]
	return por

def binarySearchCount(arr, n, key):
	left = 0
	right = n - 1
	count = 0
	while left <= right:
		mid = int((right + left) / 2)
		if arr[mid] < key:
			count = mid + 1
			left = mid + 1
		else:
			right = mid - 1
	return count

def countdig(n):
	c = 0
	while n > 0:
		n //= 10
		c += 1
	return c

def binary(x, length):
	y = bin(x)[2:]
	return y if len(y) >= length else '0' * (length - len(y)) + y

def countGreater(arr, n, k):
	l = 0
	r = n - 1
	leftGreater = n
	while l <= r:
		m = int(l + (r - l) / 2)
		if arr[m] >= k:
			leftGreater = m
			r = m - 1
		else:
			l = m + 1
	return n - leftGreater
(n, k) = map(int, input().split())
l = [0] * (2 * 10 ** 5 + 2)
ma = 0
rt = []
for i in range(n):
	(a, b) = map(int, input().split())
	rt.append((a, b, i + 1))
	ma = max(b, ma)
	l[a] += 1
	l[b + 1] -= 1
s1 = SegmentTree(l)
rt.sort()
t = 0
g = []
heapq.heapify(g)
ans = []
for i in range(1, ma + 1):
	cou = s1.query(0, i)
	while t < n and rt[t][0] <= i:
		heapq.heappush(g, (-rt[t][1], rt[t][0], rt[t][2]))
		t += 1
		if t == n:
			break
	if cou > k:
		c = cou - k
		for i in range(c):
			(r, l1, ind) = heapq.heappop(g)
			ans.append(ind)
			r *= -1
			l[l1] -= 1
			l[r + 1] += 1
			s1.__setitem__(l1, l[l1])
			s1.__setitem__(r + 1, l[r + 1])
print(len(ans))
print(*ans)


import heapq
(n, k) = list(map(int, input().split()))
llis = [[] for i in range(2 * 10 ** 5 + 1)]
rlis = [[] for i in range(2 * 10 ** 5 + 1)]
flag = [0] * (2 * 10 ** 5 + 1)
for i in range(n):
	(l, r) = list(map(int, input().split()))
	llis[l].append([i + 1, r])
	rlis[r].append([i + 1, l])
now = 0
rq = []
ans = []
for i in range(2 * 10 ** 5):
	i += 1
	for j in llis[i]:
		now += 1
		ind = j[0]
		r = j[1]
		flag[ind] = 1
		heapq.heappush(rq, [-1 * r, ind])
	for j in rlis[i - 1]:
		ind = j[0]
		if flag[ind] == 1:
			now -= 1
			flag[ind] = 0
	while now > k:
		nowq = heapq.heappop(rq)
		ind = nowq[1]
		if flag[ind] == 1:
			ans.append(ind)
			now -= 1
			flag[ind] = 0
print(len(ans))
print(' '.join(map(str, ans)))


class FTree:

	def __init__(self, f):
		self.n = len(f)
		self.ft = [0] * (self.n + 1)
		for i in range(1, self.n + 1):
			self.ft[i] += f[i - 1]
			if i + self.lsone(i) <= self.n:
				self.ft[i + self.lsone(i)] += self.ft[i]

	def lsone(self, s):
		return s & -s

	def query(self, i, j):
		if i > 1:
			return self.query(1, j) - self.query(1, j - 1)
		s = 0
		while j > 0:
			s += self.ft[j]
			j -= self.lsone(j)
		return s

	def update(self, i, v):
		while i <= self.n:
			self.ft[i] += v
			i += self.lsone(i)

	def select(self, k):
		lo = 1
		hi = self.n
		for i in range(30):
			mid = (lo + hi) // 2
			if self.query(1, mid) < k:
				lo = mid
			else:
				hi = mid
		return hi

class RUPQ:

	def __init__(self, n):
		self.ftree = FTree([0] * n)

	def query(self, i):
		return self.ftree.query(1, i)

	def update(self, i, j, v):
		self.ftree.update(i, v)
		self.ftree.update(j + 1, -v)

class RURQ:

	def __init__(self, n):
		self.f = FTree([0] * n)
		self.r = RUPQ(n)

	def query(self, i, j):
		if i > 1:
			return self.query(1, j) - self.query(1, i - 1)
		return self.r.query(j) * j - self.f.query(1, j)

	def update(self, i, j, v):
		self.r.update(i, j, v)
		self.f.update(i, v * (i - 1))
		self.f.update(j + 1, -1 * v * j)
import sys, heapq
(n, k) = [int(i) for i in sys.stdin.readline().split()]
mmn = 1
mmx = 200000
ftree = RUPQ(mmx)
lns = sys.stdin.readlines()
bds = []
qqq = 0
for ln in lns:
	qqq += 1
	t = [int(i) for i in ln.split()]
	t.append(qqq)
	bds.append(t)
	ftree.update(bds[-1][0], bds[-1][1], 1)
bds.sort()
bind = 0
heap = []
ans = []
for i in range(1, mmx + 1):
	while bind < n and bds[bind][0] == i:
		heapq.heappush(heap, (-1 * bds[bind][1], bds[bind][2]))
		bind += 1
	while ftree.query(i) > k:
		(bd, bnd) = heapq.heappop(heap)
		ans.append(bnd)
		ftree.update(i, -1 * bd, -1)
print(len(ans))
print(*ans)


from bisect import bisect_right, bisect_left

class BITbisect:

	def __init__(self, InputProbNumbers):
		self.ind_to_co = [-10 ** 18]
		self.co_to_ind = {}
		for (ind, num) in enumerate(sorted(list(set(InputProbNumbers)))):
			self.ind_to_co.append(num)
			self.co_to_ind[num] = ind + 1
		self.max = len(self.co_to_ind)
		self.data = [0] * (self.max + 1)

	def __str__(self):
		retList = []
		for i in range(1, self.max + 1):
			x = self.ind_to_co[i]
			if self.count(x):
				c = self.count(x)
				for _ in range(c):
					retList.append(x)
		return '[' + ', '.join([str(a) for a in retList]) + ']'

	def __getitem__(self, key):
		key += 1
		s = 0
		ind = 0
		l = self.max.bit_length()
		for i in reversed(range(l)):
			if ind + (1 << i) <= self.max:
				if s + self.data[ind + (1 << i)] < key:
					s += self.data[ind + (1 << i)]
					ind += 1 << i
		if ind == self.max or key < 0:
			raise IndexError('BIT index out of range')
		return self.ind_to_co[ind + 1]

	def __len__(self):
		return self._query_sum(self.max)

	def __contains__(self, num):
		if not num in self.co_to_ind:
			return False
		return self.count(num) > 0

	def _query_sum(self, i):
		s = 0
		while i > 0:
			s += self.data[i]
			i -= i & -i
		return s

	def _add(self, i, x):
		while i <= self.max:
			self.data[i] += x
			i += i & -i

	def push(self, x):
		if not x in self.co_to_ind:
			raise KeyError('The pushing number didnt initialized')
		self._add(self.co_to_ind[x], 1)

	def delete(self, x):
		if not x in self.co_to_ind:
			raise KeyError('The deleting number didnt initialized')
		if self.count(x) <= 0:
			raise ValueError('The deleting number doesnt exist')
		self._add(self.co_to_ind[x], -1)

	def count(self, x):
		return self._query_sum(self.co_to_ind[x]) - self._query_sum(self.co_to_ind[x] - 1)

	def bisect_right(self, x):
		if x in self.co_to_ind:
			i = self.co_to_ind[x]
		else:
			i = bisect_right(self.ind_to_co, x) - 1
		return self._query_sum(i)

	def bisect_left(self, x):
		if x in self.co_to_ind:
			i = self.co_to_ind[x]
		else:
			i = bisect_left(self.ind_to_co, x)
		if i == 1:
			return 0
		return self._query_sum(i - 1)
import sys
input = sys.stdin.readline
from collections import Counter
MAX = 2 * 10 ** 5 + 3
(N, K) = map(int, input().split())
Query = [list(map(int, input().split())) for _ in range(N)]
A = [[] for _ in range(MAX)]
B = BITbisect(list(range(MAX)))
P = [[] for _ in range(MAX)]
for (i, (l, r)) in enumerate(Query):
	A[l].append(r)
	P[r].append((l, i + 1))
mustL = []
for n in range(MAX):
	for r in A[n]:
		B.push(r)
	while len(B) > 0:
		b = B[0]
		if b < n:
			B.delete(b)
		else:
			break
	l = len(B)
	d = l - K
	if d > 0:
		for _ in range(d):
			b = B[l - 1]
			B.delete(b)
			mustL.append(b)
			l -= 1
C = Counter(mustL)
ans = []
for (r, c) in C.items():
	P[r].sort()
	for i in range(c):
		ans.append(P[r][i][1])
print(len(ans))
print(*ans)


import heapq
(N, K) = [int(x) for x in input().split()]
h = [[] for i in range(200000)]
for i in range(N):
	(l, r) = [int(x) for x in input().split()]
	h[l - 1].append([-(r - 1), i + 1])
g = []
t = []
heapq.heapify(t)
hist = [0] * 200000
exited = 0
for l in range(200000):
	for ri in h[l]:
		heapq.heappush(t, ri)
		hist[-ri[0]] += 1
	while len(t) - exited > K:
		top = heapq.heappop(t)
		hist[-top[0]] -= 1
		g.append(top[1])
	exited += hist[l]
print(len(g))
print(*g)