import std.stdio;
import std.ascii;
import std.range;
import std.array;
import std.functional;
import std.algorithm;
import std.conv;
import std.container;
import std.math;
import std.numeric;
import std.string;
import std.c.string;
import std.random;
import std.regex;
import std.typecons;

const EPS = 1e-8;

/* 鬆伜沺譛ィ繝ゥ繧、繝悶Λ繝ェ.
 *   Node : 鬆伜沺譛ィ縺ョ蜷?ヮ繝シ繝? *   construct(Point[] ps) 
 *      : ps(x蠎ァ讓吶〒繧ス繝シ繝医＆繧後◆轤ケ髮?粋)繧偵ｂ縺ィ縺ォ鬆伜沺譛ィ繧剃ス懈?.
 *   query(Node root, long sx, long sy, long gx, long gy) 
 *      : root縺ォ蜷ォ縺セ繧後ｋ轤ケ縺ョ縺?■, (sx <= x <= gx && sy <= y <= gy)縺ェ繧九ｂ縺ョ縺ョ蛟区焚繧定ソ斐☆.
 */
struct Point {
    double x, y;
    int id;
    int opCmp(in Point p) const {
        if (abs(y - p.y) <= EPS) return 0;
        return cast(int)((y - p.y) / abs(y - p.y));
    }
}
class Node {
    Node parent;
    Node left, right;
    double left_x, right_x;
    Point[] P;
    override string toString() const {
        return format("%s -> P: %s", [left_x, right_x], P);
    }
}
Node construct(in Point[] ps) {
    auto n = new Node;
    n.left_x = ps.front.x;
    n.right_x = ps.back.x;
    if (ps.length == 1) {
        n.P = ps.dup;
        return n;
    }
    Node l = construct(ps[0 .. $ / 2]),
         r = construct(ps[$ / 2 .. $]);
    l.parent = n;
    r.parent = n;
    n.left = l;
    n.right = r;
    size_t li = 0, ri = 0;
    Point[] P;
    while (true) {
        if (li >= l.P.length && ri >= r.P.length) break;
        if (li >= l.P.length) P ~= r.P[ri++];
        else if (ri >= r.P.length) P ~= l.P[li++];
        else {
            P ~= (l.P[li].y < r.P[ri].y ? l.P[li++] : r.P[ri++]);
        }
    }
    n.P = P;
    return n;
}
/* (sx <= x <= gx && sy <= y <= gy)縺ェ繧狗せ(x, y)縺ョ蛟区焚繧定ソ斐☆ 
 * 髢牙玄髢薙↑縺ョ豕ィ諢?*/
Point[] query(Node root, double sx, double gx, double sy, double gy) {
    //writeln("query: ", [sx, gx, sy, gy]);
    if (gx + EPS < root.left_x || root.right_x < sx - EPS) {
        return [];
    } else if (sx - EPS <= root.left_x && root.right_x <= gx + EPS) {
        auto P = assumeSorted(root.P);
        return array( P.upperBound(Point(0, sy - EPS, -1)).lowerBound(Point(0, gy + EPS, -1)) );
    } else {
        return query(root.left, sx, gx, sy, gy) ~ query(root.right, sx, gx, sy, gy);
    }
}

void main() {
    int N; double R; scanf("%d %lf\n", &N, &R);
    Point[] P = new Point[N];
    foreach (int i; 0 .. N) {
        double x, y; scanf("%lf %lf\n", &x, &y);
        P[i] = Point(x, y, i);
    }
    P.sort!"a.x < b.x";
    auto rtree = construct(P);
    auto used = new bool[N];
    void dump(Node n, int level = 0) {
        if (n is null) return;
        foreach (i; 0 .. level) write(" ");
        writeln(n);
        dump(n.left);
        dump(n.right);
    }
    //dump(rtree);
    int Ans = 0;
    foreach (i; 0 .. N) {
        auto p = P[i];
        if (used[p.id]) continue;
        Ans++;
        auto family = rtree.query(p.x - R, p.x + R, p.y - R, p.y + R);
        //writeln(family.map!"a.id");
        foreach (house; family) {
            used[house.id] = true;
        }
    }
    writeln(Ans);
}