#include <bits/stdc++.h>
using namespace std;
const int INF = 0x3f3f3f3f;
const long long INFLL = 1e18;
const int MOD = 1e9 + 7;
const int MAXN = 1e5 + 5;
struct node {
  long long X, Y;
  node *L, *R;
  int sz;
  node(long long x) {
    X = x;
    Y = rand();
    sz = 1;
    L = R = NULL;
  }
};
typedef node *pnode;
int sz(pnode t) { return t ? t->sz : 0; }
void upd_sz(pnode t) {
  if (t) t->sz = 1 + sz(t->L) + sz(t->R);
}
void split(pnode T, pnode &L, pnode &R, long long X) {
  if (!T)
    L = R = 0;
  else if (X < T->X)
    split(T->L, L, T->L, X), R = T;
  else
    split(T->R, T->R, R, X), L = T;
  upd_sz(T);
}
void merge(pnode &T, pnode L, pnode R) {
  if (!L || !R)
    T = L ? L : R;
  else if (L->Y > R->Y)
    merge(L->R, L->R, R), T = L;
  else
    merge(R->L, L, R->L), T = R;
  upd_sz(T);
}
void insert(pnode &T, pnode N) {
  if (!T)
    T = N;
  else if (N->Y > T->Y)
    split(T, N->L, N->R, N->X), T = N;
  else
    insert((N->X > T->X) ? T->R : T->L, N);
  upd_sz(T);
}
void erase(pnode &T, long long X) {
  if (!T)
    return;
  else if (T->X == X) {
    pnode t = T;
    merge(T, T->L, T->R);
    delete t;
  } else
    erase((X > T->X) ? T->R : T->L, X);
  upd_sz(T);
}
void eraseTree(pnode &T) {
  if (!T) return;
  eraseTree(T->L);
  eraseTree(T->R);
  delete T;
}
struct radio {
  int x, r, f;
  bool operator<(const radio &rhs) const { return r > rhs.r; }
};
pnode T[MAXN];
radio RS[MAXN];
int n, k;
long long ans;
int main() {
  scanf("%d", &n), scanf("%d", &k);
  ;
  for (int i = 0; i < n; i++) {
    int x, r, f;
    scanf("%d", &x), scanf("%d", &r), scanf("%d", &f);
    ;
    RS[i] = {x, r, f};
  }
  sort(RS, RS + n);
  for (int i = 0; i < n; i++) {
    int x = RS[i].x, r = RS[i].r, f = RS[i].f;
    for (int j = max(1, f - k); j < f + k + 1; j++) {
      pnode L, mid, R;
      split(T[j], L, R, x + r);
      split(L, L, mid, x - r - 1);
      ans += sz(mid);
      merge(L, L, mid);
      merge(T[j], L, R);
    }
    pnode N = new node(x);
    insert(T[f], N);
  }
  printf("%lld\n", ans);
  return 0;
}
