Recently Monocarp got a job. His working day lasts exactly $m$ minutes. During work, Monocarp wants to drink coffee at certain moments: there are $n$ minutes $a_1, a_2, \dots, a_n$, when he is able and willing to take a coffee break (for the sake of simplicity let's consider that each coffee break lasts exactly one minute). 

However, Monocarp's boss doesn't like when Monocarp takes his coffee breaks too often. So for the given coffee break that is going to be on minute $a_i$, Monocarp must choose the day in which he will drink coffee during the said minute, so that every day at least $d$ minutes pass between any two coffee breaks. Monocarp also wants to take these $n$ coffee breaks in a minimum possible number of working days (he doesn't count days when he is not at work, and he doesn't take coffee breaks on such days). Take into account that more than $d$ minutes pass between the end of any working day and the start of the following working day.

For each of the $n$ given minutes determine the day, during which Monocarp should take a coffee break in this minute. You have to minimize the number of days spent. 


-----Input-----

The first line contains three integers $n$, $m$, $d$ $(1 \le n \le 2\cdot10^{5}, n \le m \le 10^{9}, 1 \le d \le m)$ — the number of coffee breaks Monocarp wants to have, the length of each working day, and the minimum number of minutes between any two consecutive coffee breaks.

The second line contains $n$ distinct integers $a_1, a_2, \dots, a_n$ $(1 \le a_i \le m)$, where $a_i$ is some minute when Monocarp wants to have a coffee break.


-----Output-----

In the first line, write the minimum number of days required to make a coffee break in each of the $n$ given minutes. 

In the second line, print $n$ space separated integers. The $i$-th of integers should be the index of the day during which Monocarp should have a coffee break at minute $a_i$. Days are numbered from $1$. If there are multiple optimal solutions, you may print any of them.


-----Examples-----
Input
4 5 3
3 5 1 2

Output
3
3 1 1 2 

Input
10 10 1
10 5 7 4 6 3 2 1 9 8

Output
2
2 1 1 2 2 1 2 1 1 2 



-----Note-----

In the first example, Monocarp can take two coffee breaks during the first day (during minutes $1$ and $5$, $3$ minutes will pass between these breaks). One break during the second day (at minute $2$), and one break during the third day (at minute $3$).

In the second example, Monocarp can determine the day of the break as follows: if the minute when he wants to take a break is odd, then this break is on the first day, if it is even, then this break is on the second day.

Source: codeforces | Difficulty: MEDIUM_HARD
Tags: Sorting

Amortized analysis

Data structures

Greedy algorithms


Solutions:
(n, m, d) = map(int, input().split())
a = list(map(int, input().split()))
l1 = [[a[i], i] for i in range(n)]
l1.sort()
ans = [0] * n
(j, k) = (0, 0)
for i in range(n):
	if l1[i][0] - l1[j][0] <= d:
		k += 1
		ans[l1[i][1]] = k
	else:
		ans[l1[i][1]] = ans[l1[j][1]]
		j += 1
print(k)
print(*ans, sep=' ')


from sys import stdin
inp = stdin.readline
(n, m, d) = list(map(int, inp().split()))
a = [(int(minute), index) for (index, minute) in enumerate(inp().split())]
ans = [0] * n
a.sort()
ans[a[0][1]] = 1
max_cur_day = 1
j = 0
count = 1
for i in range(1, n):
	if a[i][0] - a[j][0] > d:
		ans[a[i][1]] = ans[a[j][1]]
		j += 1
	else:
		count += 1
		ans[a[i][1]] = count
print(count)
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')
from collections import Counter
(n, work, gap) = map(int, input().split())
a = list(map(int, input().split()))
a = sorted([(a[i], i) for i in range(n)])
ans = [0] * n
day = 0
left = right = 0
while right < n:
	if a[right][0] - a[left][0] <= gap:
		day += 1
		ans[a[right][1]] = day
	else:
		ans[a[right][1]] = ans[a[left][1]]
		left += 1
	right += 1
print(day)
print(*ans)


import os
import sys
from io import BytesIO, IOBase
from math import log2, ceil, sqrt, gcd, log
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')
g = lambda : input().strip()
gl = lambda : g().split()
gil = lambda : [int(var) for var in gl()]
gfl = lambda : [float(var) for var in gl()]
gcl = lambda : list(g())
gbs = lambda : [int(var) for var in g()]
rr = lambda x: reversed(range(x))
mod = int(1000000000.0) + 7
inf = float('inf')
(n, m, d) = gil()
a = [(v, i) for (i, v) in enumerate(gil())]
a.sort()
fin = [0] * n

def isPos(x):
	i = 0
	while i + x < n:
		if a[i + x][0] - a[i][0] - 1 < d:
			return False
		i += 1
	return True
(l, r) = (1, n)
ans = n
while l <= r:
	mid = (l + r) // 2
	if isPos(mid):
		r = mid - 1
		ans = mid
	else:
		l = mid + 1
for i in range(n):
	fin[a[i][1]] = 1 + i % ans
print(ans)
print(*fin)


import math
from decimal import *
getcontext().prec = 30
(n, m, d) = map(int, input().split())
a = list(map(int, input().split()))
b = sorted(a)
b.insert(0, 0)
b.insert(n + 1, 10 ** 10)
day = 1

def bs(l, r, tar):
	if l > r:
		return -1
	mid = l + (r - l) // 2
	if b[mid] >= tar and hi[mid - 1] == 1:
		return mid
	if b[mid + 1] >= tar and b[mid] < tar:
		return mid + 1
	if b[mid] >= tar and b[mid - 1] < tar:
		return mid
	if b[mid] > tar:
		return bs(l, mid - 1, tar)
	return bs(mid + 1, r, tar)
ans = n
last = 2
hi = [0] * (n + 2)
dict = {}
for i in range(1, n + 1):
	target = b[i] + d + 1
	if b[n] < target or hi[n] == 1:
		ind = 10
		if hi[i] != 1:
			dict[b[i]] = day
			day += 1
			hi[i] = 1
	else:
		index = bs(last, n, target)
		if index == -1:
			c = 10
			if hi[i] != 1:
				dict[b[i]] = day
				day += 1
				hi[i] = 1
			continue
		ans -= 1
		last = index + 1
		if hi[i] != 1:
			dict[b[i]] = day
			day += 1
		dict[b[index]] = dict[b[i]]
		hi[index] = 1
		hi[i] = 1
print(ans)
f = list()
for val in a:
	f.append(dict[val])
print(*f)


from copy import deepcopy
import itertools
from bisect import bisect_left
from bisect import bisect_right
import math
from collections import deque
from collections import Counter

def read():
	return int(input())

def readmap():
	return map(int, input().split())

def readlist():
	return list(map(int, input().split()))
(n, m, d) = readmap()
A = readlist()
Aind = dict([(A[i], i) for i in range(n)])
A.sort()
q = deque()
a = A[0]
ans = [0] * n
ans[Aind[a]] = 1
maxday = 1
q.append((a, 1))
for i in range(1, n):
	if A[i] > q[0][0] + d:
		ans[Aind[A[i]]] = q[0][1]
		q.append((A[i], q[0][1]))
		q.popleft()
	else:
		maxday += 1
		ans[Aind[A[i]]] = maxday
		q.append((A[i], maxday))
print(maxday)
print(' '.join(list(map(str, ans))))


from collections import deque

def follow(idx, this_or_first_free):
	if idx == -2:
		return -2
	if this_or_first_free[idx] == -1:
		return idx
	if this_or_first_free[idx] == -2:
		return -2
	root = follow(this_or_first_free[idx], this_or_first_free)
	this_or_first_free[idx] = root
	return root

def take(idx, this_or_first_free, initial_next):
	this_or_first_free[idx] = initial_next[idx]

def legit(idx):
	return idx != -1 and idx != -2
(n, m, d) = list(map(int, input().split()))
break_list = list([(int(idx_val[1]), idx_val[0]) for idx_val in enumerate(input().split())])
break_list.sort()
assignment = [-1] * n
breaks_initial_next = [-2] * n
TFO = [False] * n
deq = deque()
for i in range(n):
	val = break_list[i][0]
	deq.append((val, i))
	while len(deq) > 0 and val - deq[0][0] - 1 >= d:
		breaks_initial_next[deq[0][1]] = i
		deq.popleft()
head_initial_next = [i + 1 for i in range(n)]
head_initial_next[-1] = -2
head_first_free = [-1] * n
first_not_taken = 0
days_count = 0
while legit(first_not_taken):
	current = first_not_taken
	days_count += 1
	while legit(current):
		take(current, head_first_free, head_initial_next)
		assignment[break_list[current][1]] = days_count
		if not TFO[current]:
			TFO[current] = True
			current = breaks_initial_next[current]
		current = follow(current, head_first_free)
	first_not_taken = follow(first_not_taken, head_first_free)
print(days_count)
print(str(assignment)[1:-1].replace(',', ''))


from sys import stdin
from collections import defaultdict
import heapq
input = stdin.readline
(n, m, d) = map(int, input().split())
a = list(map(int, input().split()))
idx = defaultdict(int)
for i in range(n):
	idx[a[i]] = i
group = []
a.sort()
num = 1
ans = [0] * n
for aa in a:
	if len(group) == 0:
		heapq.heappush(group, (aa, num))
		ans[idx[aa]] = num
		continue
	(last_num, group_num) = heapq.heappop(group)
	if aa - last_num > d:
		ans[idx[aa]] = group_num
		heapq.heappush(group, (aa, group_num))
	else:
		num += 1
		ans[idx[aa]] = num
		heapq.heappush(group, (last_num, group_num))
		heapq.heappush(group, (aa, num))
print(num)
print(*ans)


import bisect
import collections
import copy
import functools
import heapq
import itertools
import math
import sys
import string
import random
from typing import List
sys.setrecursionlimit(99999)
(n, m, d) = map(int, input().split())
arr = list(map(int, input().split()))
a_d = [[x, i] for (i, x) in enumerate(arr)]
a_d.sort()
ans = [0] * n
ds = 1
ts = []
for (t, ind) in a_d:
	if ts and t - ts[0][0] > d:
		(_, dst) = heapq.heappop(ts)
		ans[ind] = dst
		heapq.heappush(ts, [t, dst])
	else:
		heapq.heappush(ts, [t, ds])
		ans[ind] = ds
		ds += 1
print(ds - 1)
print(*ans)


import sys
input = sys.stdin.buffer.readline
from heapq import heappush, heappop, heapify
(n, m, d) = map(int, input().split())
a = list(map(int, input().split()))
ans = [0 for i in range(n)]
arr = []
he_one = []
he_two = []
for i in range(n):
	heappush(he_one, [a[i], i])
heapify(he_one)
heapify(he_two)
day = 1
while he_one:
	(value, indx) = heappop(he_one)
	if he_two and value - d > he_two[0][0]:
		(v, dd) = heappop(he_two)
		ans[indx] = dd
		heappush(he_two, [value, dd])
	else:
		heappush(he_two, [value, day])
		ans[indx] = day
		day += 1
print(max(ans))
print(*ans)


from collections import deque

def main():
	(n, m, d) = list(map(int, input().split()))
	aa = list(map(int, input().split()))
	(q, cnt) = (deque(((-d, 1),)), 1)
	for i in sorted(list(range(n)), key=aa.__getitem__):
		a = aa[i]
		(b, j) = q.popleft()
		if a <= b + d:
			q.appendleft((b, j))
			j = cnt = cnt + 1
		aa[i] = j
		q.append((a, j))
	print(cnt)
	print(' '.join(list(map(str, aa))))

def __starting_point():
	main()
__starting_point()


from collections import defaultdict, Counter
from math import sqrt, log10, log2, log, gcd, floor, factorial
from bisect import bisect_left, bisect_right
from itertools import combinations, combinations_with_replacement
import sys, io, os
input = sys.stdin.readline
input = io.BytesIO(os.read(0, os.fstat(0).st_size)).readline
mod = 10 ** 9 + 7
inf = float('inf')

def get_list():
	return [int(i) for i in input().split()]
yn = lambda a: print('YES' if a else 'NO')
ceil = lambda a, b: (a + b - 1) // b
t = 1

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))
for i in range(t):
	(n, m, d) = [int(i) for i in input().split()]
	l = [int(i) for i in input().split()]
	dict = defaultdict(int)
	s = SortedList(l)
	currentday = 0
	while len(s):
		currentday += 1
		last = s.pop(0)
		dict[last] = currentday
		while 1:
			indexa = s.bisect_left(last + d + 1)
			if indexa < len(s):
				last = s.pop(indexa)
				dict[last] = currentday
			else:
				break
	print(currentday)
	for i in l:
		print(dict[i], end=' ')


from operator import itemgetter
(n, m, d) = map(int, input().split())
ai = list(map(int, input().split()))
ai2 = [[ai[i], i] for i in range(n)]
d += 1
ai2.sort(key=itemgetter(0))
ai4 = [0] * n
ai5 = [0] * n
ai4[0] = ai2[0][0]
ai5[0] = 1
ai[ai2[0][1]] = 1
j = 1
i = 1
z = 0
while i < n:
	if ai2[i][0] < ai4[z] + d:
		ai4[j + z] = ai2[i][0]
		ai5[j + z] = j + 1
		j += 1
		ai[ai2[i][1]] = j
	else:
		ai4[j + z] = ai2[i][0]
		ai5[j + z] = ai5[z]
		ai[ai2[i][1]] = ai5[z]
		z += 1
	i += 1
print(j)
for i in range(n):
	print(ai[i], end=' ')


(n, m, k) = list(map(int, input().split()))
l = list(map(int, input().split()))
for i in range(n):
	l[i] = [l[i], i]
l.sort()
uk1 = 1
uk2 = n

def pos(n):
	cnt = [-10000000001] * len(l)
	nonlocal k
	for i in range(len(l)):
		if l[i][0] - cnt[i % n] <= k:
			return False
		else:
			cnt[i % n] = l[i][0]
	return True
while uk2 - uk1 > 1:
	if pos((uk2 + uk1) // 2):
		uk2 = (uk1 + uk2) // 2
	else:
		uk1 = (uk1 + uk2) // 2
ans = [0] * n
if not pos(uk1):
	for i in range(n):
		ans[l[i][1]] = i % uk2 + 1
	print(uk2)
	for i in range(n):
		print(ans[i], end=' ')
else:
	for i in range(n):
		ans[l[i][1]] = i % uk1 + 1
	print(uk1)
	for i in range(n):
		print(ans[i], end=' ')


import math
import sys
from bisect import bisect_right, bisect_left, insort_right
from collections import Counter, defaultdict
from heapq import heappop, heappush
from itertools import accumulate
from sys import stdout
R = lambda : map(int, input().split())
(n, m, d) = R()
a = sorted(((x, i) for (i, x) in enumerate(R())))
res = [-1] * len(a)
res[0] = 0
cnt = 0
q = [(a[0][0], 0)]
for r in range(1, n):
	h = heappop(q)
	if a[r][0] - h[0] > d:
		res[r] = h[1]
	else:
		cnt += 1
		res[r] = cnt
		heappush(q, h)
	heappush(q, (a[r][0], res[r]))
print(max(res) + 1)
for t in sorted(zip(a, res), key=lambda x: x[0][1]):
	print(t[1] + 1, end=' ')


(a, b, c) = map(int, input().split())
l = list(map(int, input().split()))
l1 = [(l[i], i) for i in range(a)]
otv = [0] * a
l1 = sorted(l1, key=lambda x: x[0])
i = j = 0
k = 0
for i in range(a):
	if l1[i][0] - c <= l1[j][0]:
		k += 1
		otv[l1[i][1]] = k
	else:
		otv[l1[i][1]] = otv[l1[j][1]]
		j += 1
print(k)
print(' '.join(map(str, otv)))


from collections import Counter, defaultdict, deque
read = lambda : list(map(int, input().split()))

def solve(a, d, df):
	cnt = 1
	res = [0] * n
	Q = deque([(a[0], cnt)])
	res[df[a[0]]] = 1
	for i in range(1, n):
		if a[i] > Q[0][0] + d:
			(val, day) = Q.popleft()
			res[df[a[i]]] = day
			Q.append((a[i], day))
		else:
			cnt += 1
			res[df[a[i]]] = cnt
			Q.append((a[i], cnt))
	print(cnt)
	print(' '.join(map(str, res)))
(n, m, d) = read()
a = read()
df = {v: i for (i, v) in enumerate(a)}
a.sort()
solve(a, d, df)


(n, m, d) = map(int, input().split())
a = list(map(int, input().split()))
a = sorted([(a[i], i) for i in range(n)])
right = 0
left = 0
day = 0
ret = [0] * n
while right < n:
	if a[right][0] - a[left][0] <= d:
		day += 1
		ret[a[right][1]] = day
	else:
		ret[a[right][1]] = ret[a[left][1]]
		left += 1
	right += 1
print(day)
print(*ret)


(n, m, d) = map(int, input().split())
a = list(map(int, input().split()))
l = []
for i in range(n):
	l.append((a[i], i))
l.sort()
j = 0
ans = [0] * n
c = 0
for i in range(n):
	if l[i][0] - d <= l[j][0]:
		c += 1
		ans[l[i][1]] = c
	else:
		ans[l[i][1]] = ans[l[j][1]]
		j += 1
print(c)
print(*ans)


(n, m, d) = map(int, input().split())
a = list(map(int, input().split()))
id = {a[i]: i for i in range(n)}
a.sort()

def Solve(x):
	for i in range(x, n):
		if a[i] - a[i - x] <= d:
			return False
	return True
l = 1
r = n
while l < r:
	mid = int((l + r) / 2)
	if Solve(mid):
		r = mid
	else:
		l = mid + 1
ans = [0 for i in range(n)]
for i in range(n):
	ans[id[a[i]]] = i % l + 1
print(l)
print(' '.join(map(str, ans)))


(n, m, d) = list(map(int, input().split()))
arr = list(map(int, input().split()))
arrx = []
for i in range(n):
	arrx.append((arr[i], i))
arrx.sort()
arr1 = [0] * n
arr1[arrx[0][1]] = 1
count = 1
index = 0
for i in range(1, n):
	if arrx[i][0] >= arrx[index][0] + d + 1:
		arr1[arrx[i][1]] = arr1[arrx[index][1]]
		index += 1
	else:
		count += 1
		arr1[arrx[i][1]] = count
print(count)
print(*arr1)


(n, m, d) = map(int, input().split())
a = list(map(int, input().split()))
o = [0] * n
x = [(a[i], i) for i in range(n)]
x.sort()
u = 0
i = j = 0
while i < n:
	if x[i][0] - d <= x[j][0]:
		u += 1
		o[x[i][1]] = u
	else:
		o[x[i][1]] = o[x[j][1]]
		j += 1
	i += 1
print(u)
print(' '.join(list(map(str, o))))


def check(p):
	for i in range(n - p):
		if a[i + p] - a[i] - 1 < d:
			return False
	return True

def binSearch(a, b):
	(left, right) = (a - 1, b + 1)
	while right - left > 1:
		mid = (left + right) // 2
		if check(mid):
			right = mid
		else:
			left = mid
	return right
(n, m, d) = map(int, input().split())
a = list(map(int, input().split()))
a_ind = {i: a[i] for i in range(n)}
a.sort()
b = binSearch(1, n)
ans = {el: 0 for el in a}
for (i, el) in enumerate(a, 1):
	ans[el] = (i - 1) % b + 1
print(b)
print(' '.join(map(str, [ans[a_ind[i]] for i in range(n)])))


import sys
input = sys.stdin.readline
from collections import *
from heapq import *
(n, m, d) = map(int, input().split())
a = list(map(int, input().split()))
ia = [(i, a[i]) for i in range(n)]
ia.sort(key=lambda t: t[1])
pq = [(ia[0][1], 1)]
ans = [-1] * n
ans[ia[0][0]] = 1
for (i, ai) in ia[1:]:
	if ai - pq[0][0] >= d + 1:
		ans[i] = pq[0][1]
		heappop(pq)
		heappush(pq, (a[i], ans[i]))
	else:
		ans[i] = len(pq) + 1
		heappush(pq, (a[i], len(pq) + 1))
print(len(pq))
print(*ans)


class UnionFind:

	def __init__(self, n):
		self.par = [-1] * n
		self.rank = [0] * n

	def Find(self, x):
		if self.par[x] < 0:
			return x
		else:
			self.par[x] = self.Find(self.par[x])
			return self.par[x]

	def Unite(self, x, y):
		x = self.Find(x)
		y = self.Find(y)
		if x != y:
			if self.rank[x] < self.rank[y]:
				self.par[y] += self.par[x]
				self.par[x] = y
			else:
				self.par[x] += self.par[y]
				self.par[y] = x
				if self.rank[x] == self.rank[y]:
					self.rank[x] += 1

	def Same(self, x, y):
		return self.Find(x) == self.Find(y)

	def Size(self, x):
		return -self.par[self.Find(x)]
(n, m, d) = map(int, input().split())
A = list(map(int, input().split()))
A = [(a, i) for (i, a) in enumerate(A)]
A.sort()
import heapq
q = []
heapq.heapify(q)
uf = UnionFind(n)
for (a, i) in A:
	if not q:
		heapq.heappush(q, (a + d, i))
	elif q[0][0] < a:
		(_, j) = heapq.heappop(q)
		uf.Unite(i, j)
		heapq.heappush(q, (a + d, i))
	else:
		heapq.heappush(q, (a + d, i))
B = []
for i in range(n):
	if uf.par[i] < 0:
		B.append(i)
toid = {}
for (i, b) in enumerate(B):
	toid[b] = i
ans = [-1] * n
for i in range(n):
	ans[i] = toid[uf.Find(i)] + 1
print(max(ans))
print(*ans)


import sys, os, io

def rs():
	return sys.stdin.readline().rstrip()

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

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

def ws(s):
	sys.stdout.write(s + '\n')

def wi(n):
	sys.stdout.write(str(n) + '\n')

def wia(a):
	sys.stdout.write(' '.join([str(x) for x in a]) + '\n')
import math, datetime, functools, itertools, operator, bisect, fractions, statistics
from collections import deque, defaultdict, OrderedDict, Counter
from fractions import Fraction
from decimal import Decimal
from sys import stdout
from heapq import heappush, heappop, heapify, _heapify_max, _heappop_max, nsmallest, nlargest

def main():
	starttime = datetime.datetime.now()
	if os.path.exists('input.txt'):
		sys.stdin = open('input.txt', 'r')
		sys.stdout = open('output.txt', 'w')
	tc = 1
	for _ in range(tc):
		(n, m, d) = ria()
		a = ria()
		ca = a.copy()
		a = sorted(a)
		ans = []
		k = {}
		day = 1
		j = 0
		for i in range(n):
			if a[i] - a[j] >= d + 1:
				k[a[i]] = k[a[j]]
				j += 1
			else:
				k[a[i]] = day
				day += 1
		for i in ca:
			ans.append(k[i])
		wi(max(ans))
		wia(ans)
	endtime = datetime.datetime.now()
	time = (endtime - starttime).total_seconds() * 1000
	if os.path.exists('input.txt'):
		print('Time:', time, 'ms')

class FastReader(io.IOBase):
	newlines = 0

	def __init__(self, fd, chunk_size=1024 * 8):
		self._fd = fd
		self._chunk_size = chunk_size
		self.buffer = io.BytesIO()

	def read(self):
		while True:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, self._chunk_size))
			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, size=-1):
		while self.newlines == 0:
			b = os.read(self._fd, max(os.fstat(self._fd).st_size, self._chunk_size if size == -1 else size))
			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()

class FastWriter(io.IOBase):

	def __init__(self, fd):
		self._fd = fd
		self.buffer = io.BytesIO()
		self.write = self.buffer.write

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

class FastStdin(io.IOBase):

	def __init__(self, fd=0):
		self.buffer = FastReader(fd)
		self.read = lambda : self.buffer.read().decode('ascii')
		self.readline = lambda : self.buffer.readline().decode('ascii')

class FastStdout(io.IOBase):

	def __init__(self, fd=1):
		self.buffer = FastWriter(fd)
		self.write = lambda s: self.buffer.write(s.encode('ascii'))
		self.flush = self.buffer.flush
sys.stdin = FastStdin()
sys.stdout = FastStdout()
main()


(n, m, D) = map(int, input().split())
lst = [*map(int, input().split())]
d = {x: i for (i, x) in enumerate(lst)}
lst.sort()
(res, j, result) = ([0] * n, 0, 0)
for (i, x) in enumerate(lst):
	if x - lst[j] > D:
		res[d[x]] = res[d[lst[j]]]
		j += 1
	else:
		result += 1
		res[d[x]] = result
print(result)
print(*res)


R = lambda : map(int, input().split())
(n, m, d) = R()
a = sorted(((x, i) for (i, x) in enumerate(R())))
res = [-1] * len(a)
res[0] = 0
cnt = 0
l = 0
for r in range(1, n):
	if a[r][0] - d <= a[l][0]:
		cnt += 1
		res[r] = cnt
	else:
		res[r] = res[l]
		l += 1
print(max(res) + 1)
for t in sorted(zip(a, res), key=lambda x: x[0][1]):
	print(t[1] + 1, end=' ')


(n, work, gap) = list(map(int, input().split()))
a = list(map(int, input().split()))
a = sorted([(a[i], i) for i in range(n)])
ret = [0] * n
day = 0
left = right = 0
while right < n:
	if a[right][0] - a[left][0] <= gap:
		day += 1
		ret[a[right][1]] = day
	else:
		ret[a[right][1]] = ret[a[left][1]]
		left += 1
	right += 1
print(day)
print(*ret)


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')
from collections import deque
(n, m, de) = map(int, input().split())
de += 1
l = list(map(int, input().split()))
a = []
cop = [] + l
l.sort()
a = deque(a)
d = dict()
u = [0] * n
for i in range(n):
	t = l[i] - de
	if len(a) == 0 or t < a[0]:
		a.append(l[i])
		d.update({l[i]: len(a)})
	else:
		r = a[0]
		a.popleft()
		a.append(l[i])
		d.update({l[i]: d[r]})
print(len(a))
for j in cop:
	print(d[j], end=' ')


(n, m, d) = list(map(int, input().split()))
a = list(map(int, input().split()))
a = [[a[i], i] for i in range(n)]
a.sort()
b = [0] * n
c = []
e = 0
for i in range(n):
	if i == 0:
		b[a[i][1]] = 1
		c.append([1, a[i][0]])
		e += 1
	elif a[i][0] - c[0][1] > d:
		c[0][1] = a[i][0]
		b[a[i][1]] = c[0][0]
		j = 0
		while j * 2 + 1 < e and (c[j][1] > c[j * 2 + 1][1] or (j * 2 + 2 < e and c[j][1] > c[j * 2 + 2][1])):
			if 2 * j + 2 >= e or c[2 * j + 1][1] < c[2 * j + 2][1]:
				(c[j], c[2 * j + 1]) = (list(c[2 * j + 1]), list(c[j]))
				j = 2 * j + 1
			else:
				(c[j], c[2 * j + 2]) = (list(c[2 * j + 2]), list(c[j]))
				j = 2 * j + 2
	else:
		e += 1
		c.append([e, a[i][0]])
		b[a[i][1]] = e
print(e)
print(*b)


(n, m, d) = map(int, input().split())
b = sorted([[int(s), i] for (i, s) in enumerate(input().split())])
ans = [0] * n
day = 0
i = j = 0
while i < n:
	if b[i][0] - d <= b[j][0]:
		day += 1
		ans[b[i][1]] = day
	else:
		ans[b[i][1]] = ans[b[j][1]]
		j += 1
	i += 1
print(day)
print(*ans)


from sys import stdin, stdout
nmbr = lambda : int(stdin.readline())
lst = lambda : list(map(int, stdin.readline().split()))
for _ in range(1):
	(n, m, d) = lst()
	b = lst()
	a = sorted(b)
	ans = {}
	day = 1
	p = 0
	for i in range(n):
		v = a[i]
		if v - a[p] > d:
			ans[v] = ans[a[p]]
			p += 1
		else:
			ans[v] = day
			day += 1
	print(day - 1)
	for v in b:
		print(ans[v], end=' ')
	print()


from sys import stdin, stdout
from math import floor, gcd, fabs, factorial, fmod, sqrt, inf, log
from collections import defaultdict as dd, deque
from heapq import merge, heapify, heappop, heappush, nsmallest
from bisect import bisect_left as bl, bisect_right as br, bisect
mod = pow(10, 9) + 7
mod2 = 998244353

def inp():
	return stdin.readline().strip()

def iinp():
	return int(inp())

def out(var, end='\n'):
	stdout.write(str(var) + '\n')

def outa(*var, end='\n'):
	stdout.write(' '.join(map(str, var)) + end)

def lmp():
	return list(mp())

def mp():
	return map(int, inp().split())

def smp():
	return map(str, inp().split())

def l1d(n, val=0):
	return [val for i in range(n)]

def l2d(n, m, val=0):
	return [l1d(m, val) for j in range(n)]

def remadd(x, y):
	return 1 if x % y else 0

def ceil(a, b):
	return (a + b - 1) // b
S1 = 'abcdefghijklmnopqrstuvwxyz'
S2 = 'ABCDEFGHIJKLMNOPQRSTUVWXYZ'

def isprime(x):
	if x <= 1:
		return False
	if x in (2, 3):
		return True
	if x % 2 == 0:
		return False
	for i in range(3, int(sqrt(x)) + 1, 2):
		if x % i == 0:
			return False
	return True
(n, m, d) = mp()
arr = lmp()
arr = [(arr[i], i) for i in range(n)]
arr.sort()
sortedinds = [i[1] for i in arr]
arr = [i[0] for i in arr]
ml = [(arr[0], sortedinds[0])]
ansl = l1d(n)
ansl[sortedinds[0]] = 1
c = 2
for i in range(1, n):
	tmp = heappop(ml)
	if arr[i] - tmp[0] <= d:
		heappush(ml, tmp)
		ansl[sortedinds[i]] = c
		c += 1
	else:
		ansl[sortedinds[i]] = ansl[tmp[1]]
	heappush(ml, (arr[i], sortedinds[i]))
print(len(ml))
print(*ansl)


import heapq
(n, m, d) = list(map(int, input().split()))
a = list(map(int, input().split()))
ans = []
a = [(x, i) for (i, x) in enumerate(a)]
a.sort()
heap = []
day = 0
for (b, i) in a:
	found = False
	if len(heap) > 0:
		if heap[0][0] + d < b:
			heapq.heappush(heap, (b, i, heap[0][2]))
			ans.append(heapq.heappop(heap))
			found = True
	if not found:
		heapq.heappush(heap, (b, i, day + 1))
		day += 1
for t in heap:
	ans.append(t)
idx = [0] * n
print(day)
for i in range(len(ans)):
	idx[ans[i][1]] = ans[i][2]
for i in idx:
	print(i, end=' ')


(n, m, d) = list(map(int, input().split()))
breaks = list(map(int, input().split()))
breaks_S = sorted(breaks)
index_s = [i[0] for i in sorted(enumerate(breaks), key=lambda x: x[1])]
d += 1
answer = [-1] * n
x = 1
for i in range(n):
	while True:
		if i >= x and breaks_S[i] - breaks_S[i - x] < d:
			x += 1
		elif n - i > x and breaks_S[i + x] - breaks_S[i] < d:
			x += 1
		else:
			break
for i in range(n):
	answer[index_s[i]] = i % x + 1
print(x)
print(*answer)


import os
import sys
from io import BytesIO, IOBase
import heapq as h
from bisect import bisect_left, bisect_right
from types import GeneratorType
BUFSIZE = 8192

class FastIO(IOBase):
	newlines = 0

	def __init__(self, file):
		import os
		self.os = os
		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 = self.os.read(self._fd, max(self.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 = self.os.read(self._fd, max(self.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:
			self.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 collections as col
import math, string

def getInts():
	return [int(s) for s in input().split()]

def getInt():
	return int(input())

def getStrs():
	return [s for s in input().split()]

def getStr():
	return input()

def listStr():
	return list(input())
MOD = 10 ** 9 + 7

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))
import bisect

def solve():
	(N, M, D) = getInts()
	A = getInts()
	lookup = col.defaultdict(int)
	for (i, a) in enumerate(A):
		lookup[a] = i
	A = SortedList(A)
	ans = [0] * N
	count = 0
	days = 0
	while count < N:
		days += 1
		val = A.pop(0)
		ans[lookup[val]] = days
		count += 1
		while True:
			if count == N:
				break
			val += D + 1
			pos = A.bisect_left(val)
			if pos >= len(A):
				break
			val = A.pop(pos)
			ans[lookup[val]] = days
			count += 1
	print(days)
	print(*ans)
	return
solve()


(n, m, d) = map(int, input().split())
a = list(map(int, input().split()))
a = sorted([(a[i], i) for i in range(n)])
coffeeTable = [0] * n
minimumDays = 0
i = j = 0
while i < n:
	if a[i][0] - d <= a[j][0]:
		minimumDays += 1
		coffeeTable[a[i][1]] = minimumDays
	else:
		coffeeTable[a[i][1]] = coffeeTable[a[j][1]]
		j += 1
	i += 1
print(minimumDays)
print(' '.join(list(map(str, coffeeTable))))