import java.util.Arrays;
import java.util.Scanner;
import java.util.function.IntConsumer;
import java.util.stream.IntStream;
public class Main {
public static void main(String[] args) {
try (Scanner scanner = new Scanner(System.in)) {
int n = scanner.nextInt(), a = scanner.nextInt(), b = scanner.nextInt();
Integer[] x = IntStream.range(0, n).map(i -> scanner.nextInt()).boxed().toArray(Integer[]::new);
DivideInterval di = new DivideInterval(n);
UnionFind uf = new UnionFind(di.b << 1);
int[] num = new int[di.b << 1];
Arrays.fill(num, 0);
IntStream.range(0, n).forEach(i -> num[di.b + i] = 1);
IntBiConsumer f = (p, q) -> num[p] += num[q];
IntConsumer rec = new IntConsumer() {
@Override
public void accept(int c) {
if (di.b <= c) {
return;
}
for (int t = 0; t < 2; t++) {
if (!uf.same(c, (c << 1) + t)) {
uf.unite(c, (c << 1) + t, f);
accept((c << 1) + t);
}
}
}
};
IntStream.range(0, n).forEach(i -> {
int l = lowerBound(x, x[i] + a), r = lowerBound(x, x[i] + b + 1);
di.apply(l, r, j -> {
uf.unite(i + di.b, j, f);
rec.accept(j);
});
});
StringBuilder sb = new StringBuilder();
IntStream.range(0, n).forEach(i -> sb.append(num[uf.find(di.b + i)]).append(System.lineSeparator()));
System.out.print(sb.toString());
System.out.flush();
}
}
private static int lowerBound(Integer[] x, int value) {
return ~Arrays.binarySearch(x, value, (a, b) -> (a.compareTo(b) >= 0) ? 1 : -1);
}
/**
* セグ木状に区間を分割したときの処理
* https://github.com/NyaanNyaan/library/blob/master/data-structure/divide-interval.hpp を参考に作成
*
* 2*B 個の頂点を持つグラフを考える。
* B+i が元のグラフの頂点 i に対応する
*/
private static class DivideInterval {
final int n, b;
DivideInterval(int n) {
this.n = n;
int b = 1;
while (b < n) {
b <<= 1;
}
this.b = b;
}
/**
* O(N) 根から葉方向へ push する
*
* @param f f(p,c) : p -> c へ伝播
*/
@SuppressWarnings("unused")
void push(IntBiConsumer f) {
for (int p = 1; p < b; p++) {
f.accept(p, p << 1);
f.accept(p, (p << 1) | 1);
}
}
/**
* O(N) 葉から根の方向に update する
*
* @param f f(p, c1, c2) : c1 と c2 の結果を p へマージ
*/
@SuppressWarnings("unused")
void update(IntTriConsumer f) {
for (int p = b - 1; p > 0; p--) {
f.accept(p, p << 1, (p << 1) | 1);
}
}
/**
* [l, r) に対応する index の列を返す
*
* 順番は左から右へ並んでいる
* 例: [1, 11) : [1, 2), [2, 4), [4, 8), [8, 10), [10, 11)
*
* @param l
* @param r
* @return [l, r) に対応する index の列
*/
int[] range(int l, int r) {
if (!((0 <= l) && (l <= r) && (r <= n))) {
throw new IllegalArgumentException("l=" + l + ", r=" + r + ", n=" + n);
}
int[] il = new int[n], ir = new int[n];
int lIndex = 0, rIndex = 0;
for (l += b, r += b; l < r; l >>= 1, r >>= 1) {
if (1 == (1 & l)) {
il[lIndex++] = l++;
}
if (1 == (1 & r)) {
ir[rIndex++] = --r;
}
}
int[] result = new int[lIndex + rIndex];
System.arraycopy(il, 0, result, 0, lIndex);
for (int i = rIndex - 1; i >= 0; i--) {
result[lIndex++] = ir[i];
}
return result;
}
/**
* [l, r) に対応する index に対してクエリを投げる(区間は昇順)
*
* @param l
* @param r
* @param f f(i) : 区間 i にクエリを投げる
*/
void apply(int l, int r, IntConsumer f) {
if (!((0 <= l) && (l <= r) && (r <= n))) {
throw new IllegalArgumentException("l=" + l + ", r=" + r + ", n=" + n);
}
for (int i : range(l, r)) {
f.accept(i);
}
}
}
static interface IntBiConsumer {
void accept(int a, int b);
}
static interface IntTriConsumer {
void accept(int a, int b, int c);
}
/**
* Union Find(Disjoint Set Union)
* https://github.com/NyaanNyaan/library/blob/master/data-structure/union-find.hpp を参考に作成
*/
private static class UnionFind {
final int[] data;
UnionFind(int n) {
data = new int[n];
Arrays.fill(data, -1);
}
int find(int k) {
return (data[k] < 0) ? k : (data[k] = find(data[k]));
}
@SuppressWarnings("unused")
boolean unite(int x, int y) {
return unite(x, y, null);
}
boolean unite(int x, int y, IntBiConsumer f) {
if ((x = find(x)) == (y = find(y))) {
return false;
}
if (data[x] > data[y]) {
int t = x;
x = y;
y = t;
}
data[x] += data[y];
data[y] = x;
if (null != f) {
f.accept(x, y);
}
return true;
}
@SuppressWarnings("unused")
int size(int k) {
return -data[find(k)];
}
boolean same(int x, int y) {
return find(x) == find(y);
}
}
}