#include <bits/stdc++.h>
using namespace std;
inline long long read() {
  long long data = 0, w = 1;
  char ch = getchar();
  while (ch != '-' && (ch < '0' || ch > '9')) ch = getchar();
  if (ch == '-') w = -1, ch = getchar();
  while (ch >= '0' && ch <= '9') data = data * 10 + (ch ^ 48), ch = getchar();
  return data * w;
}
const long long maxn(100010), maxy(10020);
long long n, k, c[maxy], cntq;
struct point {
  long long x, r, f;
} a[maxn];
inline bool operator<(const point &lhs, const point &rhs) {
  return lhs.r > rhs.r;
}
inline void add(long long x, long long val) {
  while (x < maxy) c[x] += val, x += x & -x;
}
inline long long query(long long x) {
  long long ans = 0;
  while (x) ans += c[x], x -= x & -x;
  return ans;
}
inline void clean(long long x) {
  while (x < maxy) c[x] = 0, x += x & -x;
}
struct node {
  long long type, x, y, w;
} q[maxn * 5];
inline bool operator<(const node &x, const node &y) {
  return x.x < y.x || (x.x == y.x && x.type < y.type);
}
long long ans = 0;
inline void CDQ(node *l, node *r) {
  if (r - l <= 1) return;
  node *mid = l + ((r - l) >> 1);
  CDQ(l, mid);
  CDQ(mid, r);
  node *j = l;
  for (register node *i = mid; i != r; ++i) {
    if (!i->type) continue;
    while ((*j) < (*i) && j != mid) {
      if (!j->type) add(j->y, 1);
      ++j;
    }
    ans += 1ll * i->w * query(i->y);
  }
  for (j = l; j != mid; ++j)
    if (!j->type) clean(j->y);
  inplace_merge(l, mid, r);
}
signed main() {
  n = read();
  k = read();
  for (register long long i = 1; i <= n; i++)
    a[i] = (point){read(), read(), read()};
  sort(a + 1, a + n + 1);
  for (register long long i = 1; i <= n; i++) {
    point &p = a[i];
    long long xa = p.x - p.r, ya = max(p.f - k, 1ll);
    long long xb = p.x + p.r, yb = p.f + k;
    q[++cntq] = (node){1, xa - 1, ya - 1, 1};
    q[++cntq] = (node){1, xb, yb, 1};
    q[++cntq] = (node){1, xa - 1, yb, -1};
    q[++cntq] = (node){1, xb, ya - 1, -1};
    q[++cntq] = (node){0, p.x, p.f, 0};
  }
  CDQ(q + 1, q + cntq + 1);
  cout << ans << endl;
  return 0;
}
