#include <iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<set>
#include<map>
#include<array>
using namespace std;
#define mod 1000000007
#define test int t;scanf("%d", &t);while(t--)
#define pb push_back
#define all(x) x.begin(),x.end()
#define mpr make_pair
#define ll long long int
#define ull unsigned long long int
#define db double
#define vi vector<int>
#define vii vector<pair<int,int> >
#define pii pair<int,int>
#define vl vector<ll>
#define vll vector<pair<ll,ll> >
#define pll pair<ll,ll>
#define ub upper_bound
#define lb lower_bound

#define sc(x) scanf("%d",&x)
#define sc2(x,y) scanf("%d%d",&x,&y)
#define sc3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define sc4(w,x,y,z) scanf("%d%d%d%d",&w,&x,&y,&z)

#define scll(x) scanf("%lld",&x)
#define scll2(x,y) scanf("%lld%lld",&x,&y)
#define scll3(x,y,z) scanf("%lld%lld%lld",&x,&y,&z)
#define scll4(w,x,y,z) scanf("%lld%lld%lld%lld",&w,&x,&y,&z)

#define scdb(x) scanf("%lf",&x)
#define scdb2(x,y) scanf("%lf%lf",&x,&y)
#define scdb3(x,y,z) scanf("%lf%lf%lf",&x,&y,&z)
#define scdb4(w,x,y,z) scanf("%lf%lf%lf%lf",&w,&x,&y,&z)

#define scs(s) scanf("%s", s)

#define pr(x) printf("%d\n",x)
#define pr2(x,y) printf("%d %d\n",x,y)
#define pr3(x,y,z) printf("%d %d %d\n",x,y,z)
#define pr4(w,x,y,z) printf("%d %d %d %d\n",w,x,y,z)

#define prll(x) printf("%lld\n",x)
#define prll2(x,y) printf("%lld %lld\n",x,y)
#define prll3(x,y,z) printf("%lld %lld %lld\n",x,y,z)
#define prll4(w,x,y,z) printf("%lld %lld %lld %lld\n",w,x,y,z)

#define prdb(x) printf("%lf\n",x)
#define prdb2(x,y) printf("%lf %lf\n",x,y)
#define prdb3(x,y,z) printf("%lf %lf %lf\n",x,y,z)
#define prdb4(w,x,y,z) printf("%lf %lf %lf %lf\n",w,x,y,z)

#define prs(s) printf("%s\n", s)
#define prn() printf("\n")
#define prvec(v) for(int i=0;i<v.size();i++) cout << v[i] << " "
#define prpair(p) cout<<p.first<<" "<<p.second<<endl
#define F first
#define S second

#define maxf 10005
#define maxr 100005
vector<pair<int,pair<int,int> > > f[maxf];
int k, len;
int tree[maxr*10];
void update(int node, int a, int b, int i, int j, int value) {

  if(a > b || a > j || b < i) // Current segment is not within range [i, j]
    return;

  if(a == b) { // Leaf node
    tree[node] = value;
    return;
  }

  update(node*2, a, (a+b)/2, i, j, value); // Updating left child
  update(1+node*2, 1+(a+b)/2, b, i, j, value); // Updating right child

  tree[node] = tree[node*2]+tree[node*2+1]; // Updating root with max value
}
int query(int node, int a, int b, int i, int j) {

  if(a > b || a > j || b < i) return 0; // Out of range

  if(a >= i && b <= j) // Current segment is totally within range [i, j]
    return tree[node];

  int q1 = query(node*2, a, (a+b)/2, i, j); // Query left child
  int q2 = query(1+node*2, 1+(a+b)/2, b, i, j); // Query right child

  int res = q1+q2; // Return final result

  return res;
}
ll solve(int ind)
{
  ll ret = 0;
  int sz = 0;
  for(int i=max(0,ind-k);i<=min(maxf-1,ind+k);i++)
    for(int j=0;j<f[i].size();j++)sz++;
  vector<pair<pair<int,pair<int,int> >,int> > vec(sz);
  sz = 0;
  //fddjffdfjd
  for(int i=max(0,ind-k);i<=min(maxf-1,ind+k);i++)
    for(int j=0;j<f[i].size();j++)vec[sz++] = mpr(f[i][j],i);
  sort(all(vec));
  //if(ind==1)for(int i=0;i<vec.size();i++)
    //cout<<vec[i].F<<" "<<vec[i].S.F<<" "<<vec[i].S.S<<" "<<fre[i]<<endl;
  set<pair<int,int> > s;
  for(int i=0;i<vec.size();i++)
  {
    int x = vec[i].F.F, back = vec[i].F.S.F, forw = vec[i].F.S.S, fre = vec[i].S;
    while(!s.empty())
    {
      if(s.begin()->F >= x)break;
      update(1,0,len-1,s.begin()->S,s.begin()->S,0);
      s.erase(s.begin());
    }
    if(fre==ind)ret+=query(1,0,len-1,back,x);
    update(1,0,len-1,x,x,1);
    s.insert(mpr(forw,x));
  }
  while(!s.empty())
  {
    update(1,0,len-1,s.begin()->S,s.begin()->S,0);
    s.erase(s.begin());
  }
  /*for(int i=0;i<vec.size();i++)
  {
    int x = vec[i].F, back = vec[i].S.F, forw = vec[i].S.S;
    while(!s.empty())
    {
      if(s.begin()->F >= x)break;
      update(1,0,len-1,s.begin()->S,s.begin()->S,0);
      s.erase(s.begin());
    }
    if(fre[i]!=ind)ret+=query(1,0,len-1,back,x);
    else
    {
      update(1,0,len-1,x,x,1);
      s.insert(mpr(forw,x));
    }
  }
  while(!s.empty())
  {
    update(1,0,len-1,s.begin()->S,s.begin()->S,0);
    s.erase(s.begin());
  }*/
  //if(ret>0)cout<<ind<<" "<<ret<<endl;
  return ret;
}
int main()
{
  int n;
  cin>>n>>k;
  set<int> s;
  for(int i=0;i<n;i++)
  {
    int x, r, ind;
    cin>>x>>r>>ind;
    s.insert(x);
    s.insert(x-r);
    s.insert(x+r);
    f[ind].pb(mpr(x,mpr(x-r,x+r)));
  }
  map<int,int> mp;
  for(set<int>::iterator it=s.begin();it!=s.end();it++)
    mp[*it] = len++;
  for(int i=0;i<maxf;i++)
    for(int j=0;j<f[i].size();j++)
    {
      f[i][j].F = mp[f[i][j].F];
      f[i][j].S.F = mp[f[i][j].S.F];
      f[i][j].S.S = mp[f[i][j].S.S];
    }
  /*for(int i=0;i<maxf;i++)
  {
    for(int j=0;j<f[i].size();j++)cout<<f[i][j].F<<" "<<f[i][j].S.F<<" "<<f[i][j].S.S<<" "<<i<<endl;
  }*/
  ll ans = 0;
  for(int i=0;i<maxf;i++)ans+=solve(i);
  cout<<ans<<endl;
  return 0;
}


#include <iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<set>
#include<map>
#include<array>
using namespace std;
#define mod 1000000007
#define test int t;scanf("%d", &t);while(t--)
#define pb push_back
#define all(x) x.begin(),x.end()
#define mpr make_pair
#define ll long long int
#define ull unsigned long long int
#define db double
#define vi vector<int>
#define vii vector<pair<int,int> >
#define pii pair<int,int>
#define vl vector<ll>
#define vll vector<pair<ll,ll> >
#define pll pair<ll,ll>
#define ub upper_bound
#define lb lower_bound

#define sc(x) scanf("%d",&x)
#define sc2(x,y) scanf("%d%d",&x,&y)
#define sc3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define sc4(w,x,y,z) scanf("%d%d%d%d",&w,&x,&y,&z)

#define scll(x) scanf("%lld",&x)
#define scll2(x,y) scanf("%lld%lld",&x,&y)
#define scll3(x,y,z) scanf("%lld%lld%lld",&x,&y,&z)
#define scll4(w,x,y,z) scanf("%lld%lld%lld%lld",&w,&x,&y,&z)

#define scdb(x) scanf("%lf",&x)
#define scdb2(x,y) scanf("%lf%lf",&x,&y)
#define scdb3(x,y,z) scanf("%lf%lf%lf",&x,&y,&z)
#define scdb4(w,x,y,z) scanf("%lf%lf%lf%lf",&w,&x,&y,&z)

#define scs(s) scanf("%s", s)

#define pr(x) printf("%d\n",x)
#define pr2(x,y) printf("%d %d\n",x,y)
#define pr3(x,y,z) printf("%d %d %d\n",x,y,z)
#define pr4(w,x,y,z) printf("%d %d %d %d\n",w,x,y,z)

#define prll(x) printf("%lld\n",x)
#define prll2(x,y) printf("%lld %lld\n",x,y)
#define prll3(x,y,z) printf("%lld %lld %lld\n",x,y,z)
#define prll4(w,x,y,z) printf("%lld %lld %lld %lld\n",w,x,y,z)

#define prdb(x) printf("%lf\n",x)
#define prdb2(x,y) printf("%lf %lf\n",x,y)
#define prdb3(x,y,z) printf("%lf %lf %lf\n",x,y,z)
#define prdb4(w,x,y,z) printf("%lf %lf %lf %lf\n",w,x,y,z)

#define prs(s) printf("%s\n", s)
#define prn() printf("\n")
#define prvec(v) for(int i=0;i<v.size();i++) cout << v[i] << " "
#define prpair(p) cout<<p.first<<" "<<p.second<<endl
#define F first
#define S second

#define maxf 10005
#define maxr 100005
vector<pair<int,pair<int,int> > > f[maxf];
int k, len;
int tree[maxr*10];
void update(int node, int a, int b, int i, int j, int value) {

  if(a > b || a > j || b < i) // Current segment is not within range [i, j]
    return;

  if(a == b) { // Leaf node
    tree[node] = value;
    return;
  }

  update(node*2, a, (a+b)/2, i, j, value); // Updating left child
  update(1+node*2, 1+(a+b)/2, b, i, j, value); // Updating right child

  tree[node] = tree[node*2]+tree[node*2+1]; // Updating root with max value
}
int query(int node, int a, int b, int i, int j) {

  if(a > b || a > j || b < i) return 0; // Out of range

  if(a >= i && b <= j) // Current segment is totally within range [i, j]
    return tree[node];

  int q1 = query(node*2, a, (a+b)/2, i, j); // Query left child
  int q2 = query(1+node*2, 1+(a+b)/2, b, i, j); // Query right child

  int res = q1+q2; // Return final result

  return res;
}
ll solve(int ind)
{
  ll ret = 0;
  int sz = 0;
  for(int i=max(0,ind-k);i<=min(maxf-1,ind+k);i++)
    for(int j=0;j<f[i].size();j++)sz++;
  vector<pair<pair<int,pair<int,int> >,int> > vec(sz);
  sz = 0;
  for(int i=max(0,ind-k);i<=min(maxf-1,ind+k);i++)
    for(int j=0;j<f[i].size();j++)vec[sz++] = mpr(f[i][j],i);
  sort(all(vec));
  //if(ind==1)for(int i=0;i<vec.size();i++)
    //cout<<vec[i].F<<" "<<vec[i].S.F<<" "<<vec[i].S.S<<" "<<fre[i]<<endl;
  set<pair<int,int> > s;
  for(int i=0;i<vec.size();i++)
  {
    int x = vec[i].F.F, back = vec[i].F.S.F, forw = vec[i].F.S.S, fre = vec[i].S;
    while(!s.empty())
    {
      if(s.begin()->F >= x)break;
      update(1,0,len-1,s.begin()->S,s.begin()->S,0);
      s.erase(s.begin());
    }
    if(fre==ind)ret+=query(1,0,len-1,back,x);
    update(1,0,len-1,x,x,1);
    s.insert(mpr(forw,x));
  }
  while(!s.empty())
  {
    update(1,0,len-1,s.begin()->S,s.begin()->S,0);
    s.erase(s.begin());
  }
  //if(ret>0)cout<<ind<<" "<<ret<<endl;
  return ret;
}

inline int getint(){
    int _x=0,_tmp=1; char _tc=getchar();
      while( (_tc<'0'||_tc>'9')&&_tc!='-' ) _tc=getchar();
        if( _tc == '-' ) _tc=getchar() , _tmp = -1;
        while(_tc>='0'&&_tc<='9') _x*=10,_x+=(_tc-'0'),_tc=getchar();
          return _x*_tmp;
}
int main()
{
  int n;
  cin>>n>>k;
  set<int> s;
  for(int i=0;i<n;i++)
  {
    int x, r, ind;
    x = getint();
    r = getint();
    ind = getint();
    //sc3(x,r,ind);
    //cin>>x>>r>>ind;
    s.insert(x);
    s.insert(x-r);
    s.insert(x+r);
    f[ind].pb(mpr(x,mpr(x-r,x+r)));
  }
  map<int,int> mp;
  for(set<int>::iterator it=s.begin();it!=s.end();it++)
    mp[*it] = len++;
  for(int i=0;i<maxf;i++)
    for(int j=0;j<f[i].size();j++)
    {
      f[i][j].F = mp[f[i][j].F];
      f[i][j].S.F = mp[f[i][j].S.F];
      f[i][j].S.S = mp[f[i][j].S.S];
    }
  /*for(int i=0;i<maxf;i++)
  {
    for(int j=0;j<f[i].size();j++)cout<<f[i][j].F<<" "<<f[i][j].S.F<<" "<<f[i][j].S.S<<" "<<i<<endl;
  }*/
  ll ans = 0;
  for(int i=0;i<maxf;i++)ans+=solve(i);
  cout<<ans<<endl;
  return 0;
}


#include <iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<set>
#include<map>
#include<array>
using namespace std;
#define mod 1000000007
#define test int t;scanf("%d", &t);while(t--)
#define pb push_back
#define all(x) x.begin(),x.end()
#define mpr make_pair
#define ll long long int
#define ull unsigned long long int
#define db double
#define vi vector<int>
#define vii vector<pair<int,int> >
#define pii pair<int,int>
#define vl vector<ll>
#define vll vector<pair<ll,ll> >
#define pll pair<ll,ll>
#define ub upper_bound
#define lb lower_bound

#define sc(x) scanf("%d",&x)
#define sc2(x,y) scanf("%d%d",&x,&y)
#define sc3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define sc4(w,x,y,z) scanf("%d%d%d%d",&w,&x,&y,&z)

#define scll(x) scanf("%lld",&x)
#define scll2(x,y) scanf("%lld%lld",&x,&y)
#define scll3(x,y,z) scanf("%lld%lld%lld",&x,&y,&z)
#define scll4(w,x,y,z) scanf("%lld%lld%lld%lld",&w,&x,&y,&z)

#define scdb(x) scanf("%lf",&x)
#define scdb2(x,y) scanf("%lf%lf",&x,&y)
#define scdb3(x,y,z) scanf("%lf%lf%lf",&x,&y,&z)
#define scdb4(w,x,y,z) scanf("%lf%lf%lf%lf",&w,&x,&y,&z)

#define scs(s) scanf("%s", s)

#define pr(x) printf("%d\n",x)
#define pr2(x,y) printf("%d %d\n",x,y)
#define pr3(x,y,z) printf("%d %d %d\n",x,y,z)
#define pr4(w,x,y,z) printf("%d %d %d %d\n",w,x,y,z)

#define prll(x) printf("%lld\n",x)
#define prll2(x,y) printf("%lld %lld\n",x,y)
#define prll3(x,y,z) printf("%lld %lld %lld\n",x,y,z)
#define prll4(w,x,y,z) printf("%lld %lld %lld %lld\n",w,x,y,z)

#define prdb(x) printf("%lf\n",x)
#define prdb2(x,y) printf("%lf %lf\n",x,y)
#define prdb3(x,y,z) printf("%lf %lf %lf\n",x,y,z)
#define prdb4(w,x,y,z) printf("%lf %lf %lf %lf\n",w,x,y,z)

#define prs(s) printf("%s\n", s)
#define prn() printf("\n")
#define prvec(v) for(int i=0;i<v.size();i++) cout << v[i] << " "
#define prpair(p) cout<<p.first<<" "<<p.second<<endl
#define F first
#define S second

#define maxf 10005
#define maxr 100005
vector<pair<int,pair<int,int> > > f[maxf];
int k, len;
int tree[maxr*10];
void update(int node, int a, int b, int i, int j, int value) {

  if(a > b || a > j || b < i) // Current segment is not within range [i, j]
    return;

  if(a == b) { // Leaf node
    tree[node] = value;
    return;
  }

  update(node*2, a, (a+b)/2, i, j, value); // Updating left child
  update(1+node*2, 1+(a+b)/2, b, i, j, value); // Updating right child

  tree[node] = tree[node*2]+tree[node*2+1]; // Updating root with max value
}
int query(int node, int a, int b, int i, int j) {

  if(a > b || a > j || b < i) return 0; // Out of range

  if(a >= i && b <= j) // Current segment is totally within range [i, j]
    return tree[node];

  int q1 = query(node*2, a, (a+b)/2, i, j); // Query left child
  int q2 = query(1+node*2, 1+(a+b)/2, b, i, j); // Query right child

  int res = q1+q2; // Return final result

  return res;
}
ll solve(int ind)
{
  ll ret = 0;
  int sz = 0;
  for(int i=max(0,ind-k);i<=min(maxf-1,ind+k);i++)
    for(int j=0;j<f[i].size();j++)sz++;
  vector<pair<pair<int,pair<int,int> >,int> > vec(sz);
  sz = 0;
  for(int i=max(0,ind-k);i<=min(maxf-1,ind+k);i++)
    for(int j=0;j<f[i].size();j++)vec[sz++] = mpr(f[i][j],i);
  sort(all(vec));
  //if(ind==1)for(int i=0;i<vec.size();i++)
    //cout<<vec[i].F<<" "<<vec[i].S.F<<" "<<vec[i].S.S<<" "<<fre[i]<<endl;
  set<pair<int,int> > s;
  for(int i=0;i<vec.size();i++)
  {
    int x = vec[i].F.F, back = vec[i].F.S.F, forw = vec[i].F.S.S, fre = vec[i].S;
    while(!s.empty())
    {
      if(s.begin()->F >= x)break;
      update(1,0,len-1,s.begin()->S,s.begin()->S,0);
      s.erase(s.begin());
    }
    if(fre==ind)ret+=query(1,0,len-1,back,x);
    update(1,0,len-1,x,x,1);
    s.insert(mpr(forw,x));
  }
  while(!s.empty())
  {
    update(1,0,len-1,s.begin()->S,s.begin()->S,0);
    s.erase(s.begin());
  }
  //if(ret>0)cout<<ind<<" "<<ret<<endl;
  return ret;
}
int main()
{
  int n;
  cin>>n>>k;
  set<int> s;
  for(int i=0;i<n;i++)
  {
    int x, r, ind;
    sc3(x,r,ind);
    //cin>>x>>r>>ind;
    s.insert(x);
    s.insert(x-r);
    s.insert(x+r);
    f[ind].pb(mpr(x,mpr(x-r,x+r)));
  }
  map<int,int> mp;
  for(set<int>::iterator it=s.begin();it!=s.end();it++)
    mp[*it] = len++;
  for(int i=0;i<maxf;i++)
    for(int j=0;j<f[i].size();j++)
    {
      f[i][j].F = mp[f[i][j].F];
      f[i][j].S.F = mp[f[i][j].S.F];
      f[i][j].S.S = mp[f[i][j].S.S];
    }
  /*for(int i=0;i<maxf;i++)
  {
    for(int j=0;j<f[i].size();j++)cout<<f[i][j].F<<" "<<f[i][j].S.F<<" "<<f[i][j].S.S<<" "<<i<<endl;
  }*/
  ll ans = 0;
  for(int i=0;i<maxf;i++)ans+=solve(i);
  cout<<ans<<endl;
  return 0;
}


#include <iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<set>
#include<map>
#include<array>
using namespace std;
#define mod 1000000007
#define test int t;scanf("%d", &t);while(t--)
#define pb push_back
#define all(x) x.begin(),x.end()
#define mpr make_pair
#define ll long long int
#define ull unsigned long long int
#define db double
#define vi vector<int>
#define vii vector<pair<int,int> >
#define pii pair<int,int>
#define vl vector<ll>
#define vll vector<pair<ll,ll> >
#define pll pair<ll,ll>
#define ub upper_bound
#define lb lower_bound

#define sc(x) scanf("%d",&x)
#define sc2(x,y) scanf("%d%d",&x,&y)
#define sc3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define sc4(w,x,y,z) scanf("%d%d%d%d",&w,&x,&y,&z)

#define scll(x) scanf("%lld",&x)
#define scll2(x,y) scanf("%lld%lld",&x,&y)
#define scll3(x,y,z) scanf("%lld%lld%lld",&x,&y,&z)
#define scll4(w,x,y,z) scanf("%lld%lld%lld%lld",&w,&x,&y,&z)

#define scdb(x) scanf("%lf",&x)
#define scdb2(x,y) scanf("%lf%lf",&x,&y)
#define scdb3(x,y,z) scanf("%lf%lf%lf",&x,&y,&z)
#define scdb4(w,x,y,z) scanf("%lf%lf%lf%lf",&w,&x,&y,&z)

#define scs(s) scanf("%s", s)

#define pr(x) printf("%d\n",x)
#define pr2(x,y) printf("%d %d\n",x,y)
#define pr3(x,y,z) printf("%d %d %d\n",x,y,z)
#define pr4(w,x,y,z) printf("%d %d %d %d\n",w,x,y,z)

#define prll(x) printf("%lld\n",x)
#define prll2(x,y) printf("%lld %lld\n",x,y)
#define prll3(x,y,z) printf("%lld %lld %lld\n",x,y,z)
#define prll4(w,x,y,z) printf("%lld %lld %lld %lld\n",w,x,y,z)

#define prdb(x) printf("%lf\n",x)
#define prdb2(x,y) printf("%lf %lf\n",x,y)
#define prdb3(x,y,z) printf("%lf %lf %lf\n",x,y,z)
#define prdb4(w,x,y,z) printf("%lf %lf %lf %lf\n",w,x,y,z)

#define prs(s) printf("%s\n", s)
#define prn() printf("\n")
#define prvec(v) for(int i=0;i<v.size();i++) cout << v[i] << " "
#define prpair(p) cout<<p.first<<" "<<p.second<<endl
#define F first
#define S second

#define maxf 10005
#define maxr 100005
vector<pair<int,pair<int,int> > > f[maxf];
int k, len;
int tree[maxr*20];
int pos, value;
void update(int node, int a, int b) {
  if(a > b)return;
  if(a == b) { // Leaf node
    tree[node] = value;
    return;
  }
  if(pos<=(a+b)/2)update(node*2, a, (a+b)/2); // Updating left child
  else update(1+node*2, 1+(a+b)/2, b); // Updating right child
  tree[node] = tree[node*2]+tree[node*2+1]; // Updating root with max value
}
int query(int node, int a, int b, int i, int j) {
  if(a > b || a > j || b < i) return 0; // Out of range
  if(a >= i && b <= j) // Current segment is totally within range [i, j]
    return tree[node];
  return query(node*2,a,(a+b)/2,i,j)+query(1+node*2, 1+(a+b)/2, b, i, j);

}
ll solve(int ind)
{
  ll ret = 0;
  int sz = 0;
  for(int i=max(0,ind-k);i<=min(maxf-1,ind+k);i++)
    for(int j=0;j<f[i].size();j++)sz++;
  vector<pair<pair<int,pair<int,int> >,int> > vec(sz);
  sz = 0;
  for(int i=max(0,ind-k);i<=min(maxf-1,ind+k);i++)
    for(int j=0;j<f[i].size();j++)vec[sz++] = mpr(f[i][j],i);
  sort(all(vec));
  //if(ind==1)for(int i=0;i<vec.size();i++)
    //cout<<vec[i].F<<" "<<vec[i].S.F<<" "<<vec[i].S.S<<" "<<fre[i]<<endl;
  set<pair<int,int> > s;
  for(int i=0;i<vec.size();i++)
  {
    int x = vec[i].F.F, back = vec[i].F.S.F, forw = vec[i].F.S.S, fre = vec[i].S;
    while(!s.empty())
    {
      if(s.begin()->F >= x)break;
      pos = s.begin()->S;
      value = 0;
      update(1,0,len-1);
      s.erase(s.begin());
    }
    if(fre==ind)ret+=query(1,0,len-1,back,x);
    pos = x;
    value = 1;
    update(1,0,len-1);
    s.insert(mpr(forw,x));
  }
  while(!s.empty())
  {
    pos = s.begin()->S;
    value = 0;
    update(1,0,len-1);
    s.erase(s.begin());
  }
  //if(ret>0)cout<<ind<<" "<<ret<<endl;
  return ret;
}
int main()
{
  int n;
  cin>>n>>k;
  set<int> s;
  for(int i=0;i<n;i++)
  {
    int x, r, ind;
    sc3(x,r,ind);
    //cin>>x>>r>>ind;
    s.insert(x);
    s.insert(x-r);
    s.insert(x+r);
    f[ind].pb(mpr(x,mpr(x-r,x+r)));
  }
  map<int,int> mp;
  for(set<int>::iterator it=s.begin();it!=s.end();it++)
    mp[*it] = len++;
  for(int i=0;i<maxf;i++)
    for(int j=0;j<f[i].size();j++)
    {
      f[i][j].F = mp[f[i][j].F];
      f[i][j].S.F = mp[f[i][j].S.F];
      f[i][j].S.S = mp[f[i][j].S.S];
    }
  /*for(int i=0;i<maxf;i++)
  {
    for(int j=0;j<f[i].size();j++)cout<<f[i][j].F<<" "<<f[i][j].S.F<<" "<<f[i][j].S.S<<" "<<i<<endl;
  }*/
  ll ans = 0;
  for(int i=0;i<maxf;i++)ans+=solve(i);
  cout<<ans<<endl;
  return 0;
}


#include <iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<set>
#include<map>
#include<array>
using namespace std;
#define mod 1000000007
#define test int t;scanf("%d", &t);while(t--)
#define pb push_back
#define all(x) x.begin(),x.end()
#define mpr make_pair
#define ll long long int
#define ull unsigned long long int
#define db double
#define vi vector<int>
#define vii vector<pair<int,int> >
#define pii pair<int,int>
#define vl vector<ll>
#define vll vector<pair<ll,ll> >
#define pll pair<ll,ll>
#define ub upper_bound
#define lb lower_bound

#define sc(x) scanf("%d",&x)
#define sc2(x,y) scanf("%d%d",&x,&y)
#define sc3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define sc4(w,x,y,z) scanf("%d%d%d%d",&w,&x,&y,&z)

#define scll(x) scanf("%lld",&x)
#define scll2(x,y) scanf("%lld%lld",&x,&y)
#define scll3(x,y,z) scanf("%lld%lld%lld",&x,&y,&z)
#define scll4(w,x,y,z) scanf("%lld%lld%lld%lld",&w,&x,&y,&z)

#define scdb(x) scanf("%lf",&x)
#define scdb2(x,y) scanf("%lf%lf",&x,&y)
#define scdb3(x,y,z) scanf("%lf%lf%lf",&x,&y,&z)
#define scdb4(w,x,y,z) scanf("%lf%lf%lf%lf",&w,&x,&y,&z)

#define scs(s) scanf("%s", s)

#define pr(x) printf("%d\n",x)
#define pr2(x,y) printf("%d %d\n",x,y)
#define pr3(x,y,z) printf("%d %d %d\n",x,y,z)
#define pr4(w,x,y,z) printf("%d %d %d %d\n",w,x,y,z)

#define prll(x) printf("%lld\n",x)
#define prll2(x,y) printf("%lld %lld\n",x,y)
#define prll3(x,y,z) printf("%lld %lld %lld\n",x,y,z)
#define prll4(w,x,y,z) printf("%lld %lld %lld %lld\n",w,x,y,z)

#define prdb(x) printf("%lf\n",x)
#define prdb2(x,y) printf("%lf %lf\n",x,y)
#define prdb3(x,y,z) printf("%lf %lf %lf\n",x,y,z)
#define prdb4(w,x,y,z) printf("%lf %lf %lf %lf\n",w,x,y,z)

#define prs(s) printf("%s\n", s)
#define prn() printf("\n")
#define prvec(v) for(int i=0;i<v.size();i++) cout << v[i] << " "
#define prpair(p) cout<<p.first<<" "<<p.second<<endl
#define F first
#define S second

#define maxf 10005
#define maxr 100005
vector<pair<int,pair<int,int> > > f[maxf];
int k, len;
int tree[maxr*10];
void update(int node, int a, int b, int i, int j, int value) {

  if(a > b || a > j || b < i) // Current segment is not within range [i, j]
    return;

  if(a == b) { // Leaf node
    tree[node] = value;
    return;
  }

  update(node*2, a, (a+b)/2, i, j, value); // Updating left child
  update(1+node*2, 1+(a+b)/2, b, i, j, value); // Updating right child

  tree[node] = tree[node*2]+tree[node*2+1]; // Updating root with max value
}
int query(int node, int a, int b, int i, int j) {

  if(a > b || a > j || b < i) return 0; // Out of range

  if(a >= i && b <= j) // Current segment is totally within range [i, j]
    return tree[node];

  int q1 = query(node*2, a, (a+b)/2, i, j); // Query left child
  int q2 = query(1+node*2, 1+(a+b)/2, b, i, j); // Query right child

  int res = q1+q2; // Return final result

  return res;
}
ll solve(int ind)
{
  ll ret = 0;
  int sz = 0;
  for(int i=max(0,ind-k);i<=min(maxf-1,ind+k);i++)
    for(int j=0;j<f[i].size();j++)sz++;
  vector<pair<pair<int,pair<int,int> >,int> > vec(sz);
  sz = 0;
  for(int i=max(0,ind-k);i<=min(maxf-1,ind+k);i++)
    for(int j=0;j<f[i].size();j++)vec[sz++] = mpr(f[i][j],i);
  sort(all(vec));
  //if(ind==1)for(int i=0;i<vec.size();i++)
    //cout<<vec[i].F<<" "<<vec[i].S.F<<" "<<vec[i].S.S<<" "<<fre[i]<<endl;
  set<pair<int,int> > s;
  for(int i=0;i<vec.size();i++)
  {
    int x = vec[i].F.F, back = vec[i].F.S.F, forw = vec[i].F.S.S, fre = vec[i].S;
    while(!s.empty())
    {
      if(s.begin()->F >= x)break;
      update(1,0,len-1,s.begin()->S,s.begin()->S,0);
      s.erase(s.begin());
    }
    if(fre==ind)ret+=query(1,0,len-1,back,x);
    update(1,0,len-1,x,x,1);
    s.insert(mpr(forw,x));
  }
  while(!s.empty())
  {
    update(1,0,len-1,s.begin()->S,s.begin()->S,0);
    s.erase(s.begin());
  }
  /*for(int i=0;i<vec.size();i++)
  {
    int x = vec[i].F, back = vec[i].S.F, forw = vec[i].S.S;
    while(!s.empty())
    {
      if(s.begin()->F >= x)break;
      update(1,0,len-1,s.begin()->S,s.begin()->S,0);
      s.erase(s.begin());
    }
    if(fre[i]!=ind)ret+=query(1,0,len-1,back,x);
    else
    {
      update(1,0,len-1,x,x,1);
      s.insert(mpr(forw,x));
    }
  }
  while(!s.empty())
  {
    update(1,0,len-1,s.begin()->S,s.begin()->S,0);
    s.erase(s.begin());
  }*/
  //if(ret>0)cout<<ind<<" "<<ret<<endl;
  return ret;
}
int main()
{
  int n;
  cin>>n>>k;
  set<int> s;
  for(int i=0;i<n;i++)
  {
    int x, r, ind;
    cin>>x>>r>>ind;
    s.insert(x);
    s.insert(x-r);
    s.insert(x+r);
    f[ind].pb(mpr(x,mpr(x-r,x+r)));
  }
  map<int,int> mp;
  for(set<int>::iterator it=s.begin();it!=s.end();it++)
    mp[*it] = len++;
  for(int i=0;i<maxf;i++)
    for(int j=0;j<f[i].size();j++)
    {
      f[i][j].F = mp[f[i][j].F];
      f[i][j].S.F = mp[f[i][j].S.F];
      f[i][j].S.S = mp[f[i][j].S.S];
    }
  /*for(int i=0;i<maxf;i++)
  {
    for(int j=0;j<f[i].size();j++)cout<<f[i][j].F<<" "<<f[i][j].S.F<<" "<<f[i][j].S.S<<" "<<i<<endl;
  }*/
  ll ans = 0;
  for(int i=0;i<maxf;i++)ans+=solve(i);
  cout<<ans<<endl;
  return 0;
}


#include <iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<set>
#include<map>
#include<array>
using namespace std;
#define mod 1000000007
#define test int t;scanf("%d", &t);while(t--)
#define pb push_back
#define all(x) x.begin(),x.end()
#define mpr make_pair
#define ll long long int
#define ull unsigned long long int
#define db double
#define vi vector<int>
#define vii vector<pair<int,int> >
#define pii pair<int,int>
#define vl vector<ll>
#define vll vector<pair<ll,ll> >
#define pll pair<ll,ll>
#define ub upper_bound
#define lb lower_bound

#define sc(x) scanf("%d",&x)
#define sc2(x,y) scanf("%d%d",&x,&y)
#define sc3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define sc4(w,x,y,z) scanf("%d%d%d%d",&w,&x,&y,&z)

#define scll(x) scanf("%lld",&x)
#define scll2(x,y) scanf("%lld%lld",&x,&y)
#define scll3(x,y,z) scanf("%lld%lld%lld",&x,&y,&z)
#define scll4(w,x,y,z) scanf("%lld%lld%lld%lld",&w,&x,&y,&z)

#define scdb(x) scanf("%lf",&x)
#define scdb2(x,y) scanf("%lf%lf",&x,&y)
#define scdb3(x,y,z) scanf("%lf%lf%lf",&x,&y,&z)
#define scdb4(w,x,y,z) scanf("%lf%lf%lf%lf",&w,&x,&y,&z)

#define scs(s) scanf("%s", s)

#define pr(x) printf("%d\n",x)
#define pr2(x,y) printf("%d %d\n",x,y)
#define pr3(x,y,z) printf("%d %d %d\n",x,y,z)
#define pr4(w,x,y,z) printf("%d %d %d %d\n",w,x,y,z)

#define prll(x) printf("%lld\n",x)
#define prll2(x,y) printf("%lld %lld\n",x,y)
#define prll3(x,y,z) printf("%lld %lld %lld\n",x,y,z)
#define prll4(w,x,y,z) printf("%lld %lld %lld %lld\n",w,x,y,z)

#define prdb(x) printf("%lf\n",x)
#define prdb2(x,y) printf("%lf %lf\n",x,y)
#define prdb3(x,y,z) printf("%lf %lf %lf\n",x,y,z)
#define prdb4(w,x,y,z) printf("%lf %lf %lf %lf\n",w,x,y,z)

#define prs(s) printf("%s\n", s)
#define prn() printf("\n")
#define prvec(v) for(int i=0;i<v.size();i++) cout << v[i] << " "
#define prpair(p) cout<<p.first<<" "<<p.second<<endl
#define F first
#define S second

#define maxf 10005
#define maxr 100005
vector<pair<int,pair<int,int> > > f[maxf];
int k, len;
int tree[maxr*10];
void update(int node, int a, int b, int i, int j, int value) {

  if(a > b || a > j || b < i) // Current segment is not within range [i, j]
    return;

  if(a == b) { // Leaf node
    tree[node] = value;
    return;
  }

  update(node*2, a, (a+b)/2, i, j, value); // Updating left child
  update(1+node*2, 1+(a+b)/2, b, i, j, value); // Updating right child

  tree[node] = tree[node*2]+tree[node*2+1]; // Updating root with max value
}
int query(int node, int a, int b, int i, int j) {

  if(a > b || a > j || b < i) return 0; // Out of range

  if(a >= i && b <= j) // Current segment is totally within range [i, j]
    return tree[node];

  int q1 = query(node*2, a, (a+b)/2, i, j); // Query left child
  int q2 = query(1+node*2, 1+(a+b)/2, b, i, j); // Query right child

  int res = q1+q2; // Return final result

  return res;
}
ll solve(int ind)
{
  ll ret = 0;
  int sz = 0;
  for(int i=max(0,ind-k);i<=min(maxf-1,ind+k);i++)
    for(int j=0;j<f[i].size();j++)sz++;
  vector<pair<pair<int,pair<int,int> >,int> > vec(sz);
  sz = 0;
  //fdfdfjd
  for(int i=max(0,ind-k);i<=min(maxf-1,ind+k);i++)
    for(int j=0;j<f[i].size();j++)vec[sz++] = mpr(f[i][j],i);
  sort(all(vec));
  //if(ind==1)for(int i=0;i<vec.size();i++)
    //cout<<vec[i].F<<" "<<vec[i].S.F<<" "<<vec[i].S.S<<" "<<fre[i]<<endl;
  set<pair<int,int> > s;
  for(int i=0;i<vec.size();i++)
  {
    int x = vec[i].F.F, back = vec[i].F.S.F, forw = vec[i].F.S.S, fre = vec[i].S;
    while(!s.empty())
    {
      if(s.begin()->F >= x)break;
      update(1,0,len-1,s.begin()->S,s.begin()->S,0);
      s.erase(s.begin());
    }
    if(fre==ind)ret+=query(1,0,len-1,back,x);
    update(1,0,len-1,x,x,1);
    s.insert(mpr(forw,x));
  }
  while(!s.empty())
  {
    update(1,0,len-1,s.begin()->S,s.begin()->S,0);
    s.erase(s.begin());
  }
  /*for(int i=0;i<vec.size();i++)
  {
    int x = vec[i].F, back = vec[i].S.F, forw = vec[i].S.S;
    while(!s.empty())
    {
      if(s.begin()->F >= x)break;
      update(1,0,len-1,s.begin()->S,s.begin()->S,0);
      s.erase(s.begin());
    }
    if(fre[i]!=ind)ret+=query(1,0,len-1,back,x);
    else
    {
      update(1,0,len-1,x,x,1);
      s.insert(mpr(forw,x));
    }
  }
  while(!s.empty())
  {
    update(1,0,len-1,s.begin()->S,s.begin()->S,0);
    s.erase(s.begin());
  }*/
  //if(ret>0)cout<<ind<<" "<<ret<<endl;
  return ret;
}
int main()
{
  int n;
  cin>>n>>k;
  set<int> s;
  for(int i=0;i<n;i++)
  {
    int x, r, ind;
    cin>>x>>r>>ind;
    s.insert(x);
    s.insert(x-r);
    s.insert(x+r);
    f[ind].pb(mpr(x,mpr(x-r,x+r)));
  }
  map<int,int> mp;
  for(set<int>::iterator it=s.begin();it!=s.end();it++)
    mp[*it] = len++;
  for(int i=0;i<maxf;i++)
    for(int j=0;j<f[i].size();j++)
    {
      f[i][j].F = mp[f[i][j].F];
      f[i][j].S.F = mp[f[i][j].S.F];
      f[i][j].S.S = mp[f[i][j].S.S];
    }
  /*for(int i=0;i<maxf;i++)
  {
    for(int j=0;j<f[i].size();j++)cout<<f[i][j].F<<" "<<f[i][j].S.F<<" "<<f[i][j].S.S<<" "<<i<<endl;
  }*/
  ll ans = 0;
  for(int i=0;i<maxf;i++)ans+=solve(i);
  cout<<ans<<endl;
  return 0;
}


#include <iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<set>
#include<map>
#include<array>
using namespace std;
#define mod 1000000007
#define test int t;scanf("%d", &t);while(t--)
#define pb push_back
#define all(x) x.begin(),x.end()
#define mpr make_pair
#define ll long long int
#define ull unsigned long long int
#define db double
#define vi vector<int>
#define vii vector<pair<int,int> >
#define pii pair<int,int>
#define vl vector<ll>
#define vll vector<pair<ll,ll> >
#define pll pair<ll,ll>
#define ub upper_bound
#define lb lower_bound

#define sc(x) scanf("%d",&x)
#define sc2(x,y) scanf("%d%d",&x,&y)
#define sc3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define sc4(w,x,y,z) scanf("%d%d%d%d",&w,&x,&y,&z)

#define scll(x) scanf("%lld",&x)
#define scll2(x,y) scanf("%lld%lld",&x,&y)
#define scll3(x,y,z) scanf("%lld%lld%lld",&x,&y,&z)
#define scll4(w,x,y,z) scanf("%lld%lld%lld%lld",&w,&x,&y,&z)

#define scdb(x) scanf("%lf",&x)
#define scdb2(x,y) scanf("%lf%lf",&x,&y)
#define scdb3(x,y,z) scanf("%lf%lf%lf",&x,&y,&z)
#define scdb4(w,x,y,z) scanf("%lf%lf%lf%lf",&w,&x,&y,&z)

#define scs(s) scanf("%s", s)

#define pr(x) printf("%d\n",x)
#define pr2(x,y) printf("%d %d\n",x,y)
#define pr3(x,y,z) printf("%d %d %d\n",x,y,z)
#define pr4(w,x,y,z) printf("%d %d %d %d\n",w,x,y,z)

#define prll(x) printf("%lld\n",x)
#define prll2(x,y) printf("%lld %lld\n",x,y)
#define prll3(x,y,z) printf("%lld %lld %lld\n",x,y,z)
#define prll4(w,x,y,z) printf("%lld %lld %lld %lld\n",w,x,y,z)

#define prdb(x) printf("%lf\n",x)
#define prdb2(x,y) printf("%lf %lf\n",x,y)
#define prdb3(x,y,z) printf("%lf %lf %lf\n",x,y,z)
#define prdb4(w,x,y,z) printf("%lf %lf %lf %lf\n",w,x,y,z)

#define prs(s) printf("%s\n", s)
#define prn() printf("\n")
#define prvec(v) for(int i=0;i<v.size();i++) cout << v[i] << " "
#define prpair(p) cout<<p.first<<" "<<p.second<<endl
#define F first
#define S second

#define maxf 10005
#define maxr 100005
vector<pair<int,pair<int,int> > > f[maxf];
int k, len;
int tree[maxr*20];
int pos, value;
void update(int node, int a, int b) {
  if(a > b)return;
  if(a == b) { // Leaf node
    tree[node] = value;
    return;
  }
  if(pos<=(a+b)/2)update(node*2, a, (a+b)/2); // Updating left child
  else update(1+node*2, 1+(a+b)/2, b); // Updating right child
  tree[node] = tree[node*2]+tree[node*2+1]; // Updating root with max value
}
int query(int node, int a, int b, int i, int j) {
  if(a > b || a > j || b < i) return 0; // Out of range
  if(a >= i && b <= j) // Current segment is totally within range [i, j]
    return tree[node];
  return query(node*2,a,(a+b)/2,i,j)+query(1+node*2, 1+(a+b)/2, b, i, j);

}
ll solve(int ind)
{
  ll ret = 0;
  int sz = 0;
  for(int i=max(0,ind-k);i<=min(maxf-1,ind+k);i++)
    for(int j=0;j<f[i].size();j++)sz++;
  vector<pair<pair<int,pair<int,int> >,int> > vec(sz);
  sz = 0;
  for(int i=max(0,ind-k);i<=min(maxf-1,ind+k);i++)
    for(int j=0;j<f[i].size();j++)vec[sz++] = mpr(f[i][j],i);
  sort(all(vec));
  //if(ind==1)for(int i=0;i<vec.size();i++)
    //cout<<vec[i].F<<" "<<vec[i].S.F<<" "<<vec[i].S.S<<" "<<fre[i]<<endl;
  set<pair<int,int> > s;
  for(int i=0;i<vec.size();i++)
  {
    int x = vec[i].F.F, back = vec[i].F.S.F, forw = vec[i].F.S.S, fre = vec[i].S;
    while(!s.empty())
    {
      if(s.begin()->F >= x)break;
      pos = s.begin()->S;
      value = 0;
      update(1,0,len-1);
      s.erase(s.begin());
    }
    if(fre==ind)ret+=query(1,0,len-1,back,x);
    pos = x;
    value = 1;
    update(1,0,len-1);
    s.insert(mpr(forw,x));
  }
  for(set<pair<int,int> >::iterator it=s.begin();it!=s.end();it++)
  {
    pos = it->S;
    value = 0;
    update(1,0,len-1);
  }
  s.clear();
  //if(ret>0)cout<<ind<<" "<<ret<<endl;
  return ret;
}
int main()
{
  int n;
  cin>>n>>k;
  set<int> s;
  for(int i=0;i<n;i++)
  {
    int x, r, ind;
    sc3(x,r,ind);
    //cin>>x>>r>>ind;
    s.insert(x);
    s.insert(x-r);
    s.insert(x+r);
    f[ind].pb(mpr(x,mpr(x-r,x+r)));
  }
  map<int,int> mp;
  for(set<int>::iterator it=s.begin();it!=s.end();it++)
    mp[*it] = len++;
  for(int i=0;i<maxf;i++)
    for(int j=0;j<f[i].size();j++)
    {
      f[i][j].F = mp[f[i][j].F];
      f[i][j].S.F = mp[f[i][j].S.F];
      f[i][j].S.S = mp[f[i][j].S.S];
    }
  /*for(int i=0;i<maxf;i++)
  {
    for(int j=0;j<f[i].size();j++)cout<<f[i][j].F<<" "<<f[i][j].S.F<<" "<<f[i][j].S.S<<" "<<i<<endl;
  }*/
  ll ans = 0;
  for(int i=0;i<maxf;i++)ans+=solve(i);
  cout<<ans<<endl;
  return 0;
}


#include <iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<set>
#include<map>
#include<array>
using namespace std;
#define mod 1000000007
#define test int t;scanf("%d", &t);while(t--)
#define pb push_back
#define all(x) x.begin(),x.end()
#define mpr make_pair
#define ll long long int
#define ull unsigned long long int
#define db double
#define vi vector<int>
#define vii vector<pair<int,int> >
#define pii pair<int,int>
#define vl vector<ll>
#define vll vector<pair<ll,ll> >
#define pll pair<ll,ll>
#define ub upper_bound
#define lb lower_bound

#define sc(x) scanf("%d",&x)
#define sc2(x,y) scanf("%d%d",&x,&y)
#define sc3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define sc4(w,x,y,z) scanf("%d%d%d%d",&w,&x,&y,&z)

#define scll(x) scanf("%lld",&x)
#define scll2(x,y) scanf("%lld%lld",&x,&y)
#define scll3(x,y,z) scanf("%lld%lld%lld",&x,&y,&z)
#define scll4(w,x,y,z) scanf("%lld%lld%lld%lld",&w,&x,&y,&z)

#define scdb(x) scanf("%lf",&x)
#define scdb2(x,y) scanf("%lf%lf",&x,&y)
#define scdb3(x,y,z) scanf("%lf%lf%lf",&x,&y,&z)
#define scdb4(w,x,y,z) scanf("%lf%lf%lf%lf",&w,&x,&y,&z)

#define scs(s) scanf("%s", s)

#define pr(x) printf("%d\n",x)
#define pr2(x,y) printf("%d %d\n",x,y)
#define pr3(x,y,z) printf("%d %d %d\n",x,y,z)
#define pr4(w,x,y,z) printf("%d %d %d %d\n",w,x,y,z)

#define prll(x) printf("%lld\n",x)
#define prll2(x,y) printf("%lld %lld\n",x,y)
#define prll3(x,y,z) printf("%lld %lld %lld\n",x,y,z)
#define prll4(w,x,y,z) printf("%lld %lld %lld %lld\n",w,x,y,z)

#define prdb(x) printf("%lf\n",x)
#define prdb2(x,y) printf("%lf %lf\n",x,y)
#define prdb3(x,y,z) printf("%lf %lf %lf\n",x,y,z)
#define prdb4(w,x,y,z) printf("%lf %lf %lf %lf\n",w,x,y,z)

#define prs(s) printf("%s\n", s)
#define prn() printf("\n")
#define prvec(v) for(int i=0;i<v.size();i++) cout << v[i] << " "
#define prpair(p) cout<<p.first<<" "<<p.second<<endl
#define F first
#define S second

#define maxf 10005
#define maxr 100005
vector<pair<int,pair<int,int> > > f[maxf];
int k, len;
int tree[maxr*10];
void update(int node, int a, int b, int i, int value) {
  if(a > b || a > i || b < i)return;
  if(a == b) { // Leaf node
    tree[node] = value;
    return;
  }
  if(i<=(a+b)/2)update(node*2, a, (a+b)/2, i, value); // Updating left child
  else update(1+node*2, 1+(a+b)/2, b, i, value); // Updating right child
  tree[node] = tree[node*2]+tree[node*2+1]; // Updating root with max value
}
int query(int node, int a, int b, int i, int j) {
  if(a > b || a > j || b < i) return 0; // Out of range
  if(a >= i && b <= j) // Current segment is totally within range [i, j]
    return tree[node];
  return query(node*2,a,(a+b)/2,i,j)+query(1+node*2, 1+(a+b)/2, b, i, j);

}
ll solve(int ind)
{
  ll ret = 0;
  int sz = 0;
  for(int i=max(0,ind-k);i<=min(maxf-1,ind+k);i++)
    for(int j=0;j<f[i].size();j++)sz++;
  vector<pair<pair<int,pair<int,int> >,int> > vec(sz);
  sz = 0;
  for(int i=max(0,ind-k);i<=min(maxf-1,ind+k);i++)
    for(int j=0;j<f[i].size();j++)vec[sz++] = mpr(f[i][j],i);
  sort(all(vec));
  //if(ind==1)for(int i=0;i<vec.size();i++)
    //cout<<vec[i].F<<" "<<vec[i].S.F<<" "<<vec[i].S.S<<" "<<fre[i]<<endl;
  set<pair<int,int> > s;
  for(int i=0;i<vec.size();i++)
  {
    int x = vec[i].F.F, back = vec[i].F.S.F, forw = vec[i].F.S.S, fre = vec[i].S;
    while(!s.empty())
    {
      if(s.begin()->F >= x)break;
      update(1,0,len-1,s.begin()->S,0);
      s.erase(s.begin());
    }
    if(fre==ind)ret+=query(1,0,len-1,back,x);
    update(1,0,len-1,x,1);
    s.insert(mpr(forw,x));
  }
  while(!s.empty())
  {
    update(1,0,len-1,s.begin()->S,0);
    s.erase(s.begin());
  }
  //if(ret>0)cout<<ind<<" "<<ret<<endl;
  return ret;
}
int main()
{
  int n;
  cin>>n>>k;
  set<int> s;
  for(int i=0;i<n;i++)
  {
    int x, r, ind;
    sc3(x,r,ind);
    //cin>>x>>r>>ind;
    s.insert(x);
    s.insert(x-r);
    s.insert(x+r);
    f[ind].pb(mpr(x,mpr(x-r,x+r)));
  }
  map<int,int> mp;
  for(set<int>::iterator it=s.begin();it!=s.end();it++)
    mp[*it] = len++;
  for(int i=0;i<maxf;i++)
    for(int j=0;j<f[i].size();j++)
    {
      f[i][j].F = mp[f[i][j].F];
      f[i][j].S.F = mp[f[i][j].S.F];
      f[i][j].S.S = mp[f[i][j].S.S];
    }
  /*for(int i=0;i<maxf;i++)
  {
    for(int j=0;j<f[i].size();j++)cout<<f[i][j].F<<" "<<f[i][j].S.F<<" "<<f[i][j].S.S<<" "<<i<<endl;
  }*/
  ll ans = 0;
  for(int i=0;i<maxf;i++)ans+=solve(i);
  cout<<ans<<endl;
  return 0;
}


#include <iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<set>
#include<map>
#include<array>
using namespace std;
#define mod 1000000007
#define test int t;scanf("%d", &t);while(t--)
#define pb push_back
#define all(x) x.begin(),x.end()
#define mpr make_pair
#define ll long long int
#define ull unsigned long long int
#define db double
#define vi vector<int>
#define vii vector<pair<int,int> >
#define pii pair<int,int>
#define vl vector<ll>
#define vll vector<pair<ll,ll> >
#define pll pair<ll,ll>
#define ub upper_bound
#define lb lower_bound

#define sc(x) scanf("%d",&x)
#define sc2(x,y) scanf("%d%d",&x,&y)
#define sc3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define sc4(w,x,y,z) scanf("%d%d%d%d",&w,&x,&y,&z)

#define scll(x) scanf("%lld",&x)
#define scll2(x,y) scanf("%lld%lld",&x,&y)
#define scll3(x,y,z) scanf("%lld%lld%lld",&x,&y,&z)
#define scll4(w,x,y,z) scanf("%lld%lld%lld%lld",&w,&x,&y,&z)

#define scdb(x) scanf("%lf",&x)
#define scdb2(x,y) scanf("%lf%lf",&x,&y)
#define scdb3(x,y,z) scanf("%lf%lf%lf",&x,&y,&z)
#define scdb4(w,x,y,z) scanf("%lf%lf%lf%lf",&w,&x,&y,&z)

#define scs(s) scanf("%s", s)

#define pr(x) printf("%d\n",x)
#define pr2(x,y) printf("%d %d\n",x,y)
#define pr3(x,y,z) printf("%d %d %d\n",x,y,z)
#define pr4(w,x,y,z) printf("%d %d %d %d\n",w,x,y,z)

#define prll(x) printf("%lld\n",x)
#define prll2(x,y) printf("%lld %lld\n",x,y)
#define prll3(x,y,z) printf("%lld %lld %lld\n",x,y,z)
#define prll4(w,x,y,z) printf("%lld %lld %lld %lld\n",w,x,y,z)

#define prdb(x) printf("%lf\n",x)
#define prdb2(x,y) printf("%lf %lf\n",x,y)
#define prdb3(x,y,z) printf("%lf %lf %lf\n",x,y,z)
#define prdb4(w,x,y,z) printf("%lf %lf %lf %lf\n",w,x,y,z)

#define prs(s) printf("%s\n", s)
#define prn() printf("\n")
#define prvec(v) for(int i=0;i<v.size();i++) cout << v[i] << " "
#define prpair(p) cout<<p.first<<" "<<p.second<<endl
#define F first
#define S second

#define maxf 10005
#define maxr 100005
vector<pair<int,pair<int,int> > > f[maxf];
int k, len;
int tree[maxr*10];
void update(int node, int a, int b, int i, int j, int value) {

  if(a > b || a > j || b < i) // Current segment is not within range [i, j]
    return;

  if(a == b) { // Leaf node
    tree[node] = value;
    return;
  }

  update(node*2, a, (a+b)/2, i, j, value); // Updating left child
  update(1+node*2, 1+(a+b)/2, b, i, j, value); // Updating right child

  tree[node] = tree[node*2]+tree[node*2+1]; // Updating root with max value
}
int query(int node, int a, int b, int i, int j) {

  if(a > b || a > j || b < i) return 0; // Out of range

  if(a >= i && b <= j) // Current segment is totally within range [i, j]
    return tree[node];

  int q1 = query(node*2, a, (a+b)/2, i, j); // Query left child
  int q2 = query(1+node*2, 1+(a+b)/2, b, i, j); // Query right child

  int res = q1+q2; // Return final result

  return res;
}
ll solve(int ind)
{
  ll ret = 0;
  vector<pair<pair<int,pair<int,int> >,int> > vec;
  for(int i=max(0,ind-k);i<=min(maxf-1,ind+k);i++)
    for(int j=0;j<f[i].size();j++)vec.pb(mpr(f[i][j],i));
  sort(all(vec));
  //if(ind==1)for(int i=0;i<vec.size();i++)
    //cout<<vec[i].F<<" "<<vec[i].S.F<<" "<<vec[i].S.S<<" "<<fre[i]<<endl;
  set<pair<int,int> > s;
  for(int i=0;i<vec.size();i++)
  {
    int x = vec[i].F.F, back = vec[i].F.S.F, forw = vec[i].F.S.S, fre = vec[i].S;
    while(!s.empty())
    {
      if(s.begin()->F >= x)break;
      update(1,0,len-1,s.begin()->S,s.begin()->S,0);
      s.erase(s.begin());
    }
    if(fre==ind)ret+=query(1,0,len-1,back,x);
    update(1,0,len-1,x,x,1);
    s.insert(mpr(forw,x));
  }
  while(!s.empty())
  {
    update(1,0,len-1,s.begin()->S,s.begin()->S,0);
    s.erase(s.begin());
  }
  /*for(int i=0;i<vec.size();i++)
  {
    int x = vec[i].F, back = vec[i].S.F, forw = vec[i].S.S;
    while(!s.empty())
    {
      if(s.begin()->F >= x)break;
      update(1,0,len-1,s.begin()->S,s.begin()->S,0);
      s.erase(s.begin());
    }
    if(fre[i]!=ind)ret+=query(1,0,len-1,back,x);
    else
    {
      update(1,0,len-1,x,x,1);
      s.insert(mpr(forw,x));
    }
  }
  while(!s.empty())
  {
    update(1,0,len-1,s.begin()->S,s.begin()->S,0);
    s.erase(s.begin());
  }*/
  //if(ret>0)cout<<ind<<" "<<ret<<endl;
  return ret;
}
int main()
{
  int n;
  cin>>n>>k;
  set<int> s;
  for(int i=0;i<n;i++)
  {
    int x, r, ind;
    cin>>x>>r>>ind;
    s.insert(x);
    s.insert(x-r);
    s.insert(x+r);
    f[ind].pb(mpr(x,mpr(x-r,x+r)));
  }
  map<int,int> mp;
  for(set<int>::iterator it=s.begin();it!=s.end();it++)
    mp[*it] = len++;
  for(int i=0;i<maxf;i++)
    for(int j=0;j<f[i].size();j++)
    {
      f[i][j].F = mp[f[i][j].F];
      f[i][j].S.F = mp[f[i][j].S.F];
      f[i][j].S.S = mp[f[i][j].S.S];
    }
  /*for(int i=0;i<maxf;i++)
  {
    for(int j=0;j<f[i].size();j++)cout<<f[i][j].F<<" "<<f[i][j].S.F<<" "<<f[i][j].S.S<<" "<<i<<endl;
  }*/
  ll ans = 0;
  for(int i=0;i<maxf;i++)ans+=solve(i);
  cout<<ans<<endl;
  return 0;
}


#include <iostream>
#include<vector>
#include<algorithm>
#include<math.h>
#include<stdio.h>
#include<set>
#include<map>
#include<array>
using namespace std;
#define mod 1000000007
#define test int t;scanf("%d", &t);while(t--)
#define pb push_back
#define all(x) x.begin(),x.end()
#define mpr make_pair
#define ll long long int
#define ull unsigned long long int
#define db double
#define vi vector<int>
#define vii vector<pair<int,int> >
#define pii pair<int,int>
#define vl vector<ll>
#define vll vector<pair<ll,ll> >
#define pll pair<ll,ll>
#define ub upper_bound
#define lb lower_bound

#define sc(x) scanf("%d",&x)
#define sc2(x,y) scanf("%d%d",&x,&y)
#define sc3(x,y,z) scanf("%d%d%d",&x,&y,&z)
#define sc4(w,x,y,z) scanf("%d%d%d%d",&w,&x,&y,&z)

#define scll(x) scanf("%lld",&x)
#define scll2(x,y) scanf("%lld%lld",&x,&y)
#define scll3(x,y,z) scanf("%lld%lld%lld",&x,&y,&z)
#define scll4(w,x,y,z) scanf("%lld%lld%lld%lld",&w,&x,&y,&z)

#define scdb(x) scanf("%lf",&x)
#define scdb2(x,y) scanf("%lf%lf",&x,&y)
#define scdb3(x,y,z) scanf("%lf%lf%lf",&x,&y,&z)
#define scdb4(w,x,y,z) scanf("%lf%lf%lf%lf",&w,&x,&y,&z)

#define scs(s) scanf("%s", s)

#define pr(x) printf("%d\n",x)
#define pr2(x,y) printf("%d %d\n",x,y)
#define pr3(x,y,z) printf("%d %d %d\n",x,y,z)
#define pr4(w,x,y,z) printf("%d %d %d %d\n",w,x,y,z)

#define prll(x) printf("%lld\n",x)
#define prll2(x,y) printf("%lld %lld\n",x,y)
#define prll3(x,y,z) printf("%lld %lld %lld\n",x,y,z)
#define prll4(w,x,y,z) printf("%lld %lld %lld %lld\n",w,x,y,z)

#define prdb(x) printf("%lf\n",x)
#define prdb2(x,y) printf("%lf %lf\n",x,y)
#define prdb3(x,y,z) printf("%lf %lf %lf\n",x,y,z)
#define prdb4(w,x,y,z) printf("%lf %lf %lf %lf\n",w,x,y,z)

#define prs(s) printf("%s\n", s)
#define prn() printf("\n")
#define prvec(v) for(int i=0;i<v.size();i++) cout << v[i] << " "
#define prpair(p) cout<<p.first<<" "<<p.second<<endl
#define F first
#define S second

#define maxf 10005
#define maxr 100005
vector<pair<int,pair<int,int> > > f[maxf];
int k, len;
int tree[maxr*10];
void update(int node, int a, int b, int i, int j, int value) {

  if(a > b || a > j || b < i) // Current segment is not within range [i, j]
    return;

  if(a == b) { // Leaf node
    tree[node] = value;
    return;
  }

  update(node*2, a, (a+b)/2, i, j, value); // Updating left child
  update(1+node*2, 1+(a+b)/2, b, i, j, value); // Updating right child

  tree[node] = tree[node*2]+tree[node*2+1]; // Updating root with max value
}
int query(int node, int a, int b, int i, int j) {

  if(a > b || a > j || b < i) return 0; // Out of range

  if(a >= i && b <= j) // Current segment is totally within range [i, j]
    return tree[node];

  int q1 = query(node*2, a, (a+b)/2, i, j); // Query left child
  int q2 = query(1+node*2, 1+(a+b)/2, b, i, j); // Query right child

  int res = q1+q2; // Return final result

  return res;
}
ll solve(int ind)
{
  ll ret = 0;
  vector<pair<int,pair<int,int> > > vec;
  vector<int> fre;
  for(int i=ind;i<=min(maxf-1,ind+k);i++)
    for(int j=0;j<f[i].size();j++)
    {
      vec.pb(f[i][j]);
      fre.pb(i);
    }
  sort(all(vec));
  set<pair<int,int> > s;
  for(int i=0;i<vec.size();i++)
  {
    int x = vec[i].F, back = vec[i].S.F, forw = vec[i].S.S;
    while(!s.empty())
    {
      if(s.begin()->F >= x)break;
      update(1,0,len-1,s.begin()->S,s.begin()->S,0);
      s.erase(s.begin());
    }
    if(fre[i]==ind)ret+=query(1,0,len-1,back,x);
    update(1,0,len-1,x,x,1);
    s.insert(mpr(forw,x));
  }
  while(!s.empty())
  {
    update(1,0,len-1,s.begin()->S,s.begin()->S,0);
    s.erase(s.begin());
  }
  for(int i=0;i<vec.size();i++)
  {
    int x = vec[i].F, back = vec[i].S.F, forw = vec[i].S.S;
    while(!s.empty())
    {
      if(s.begin()->F >= x)break;
      update(1,0,len-1,s.begin()->S,s.begin()->S,0);
      s.erase(s.begin());
    }
    if(fre[i]!=ind)ret+=query(1,0,len-1,back,x);
    if(fre[i]==ind)
    {
      update(1,0,len-1,x,x,1);
      s.insert(mpr(forw,x));
    }
  }
  while(!s.empty())
  {
    update(1,0,len-1,s.begin()->S,s.begin()->S,0);
    s.erase(s.begin());
  }
  return ret;
}
int main()
{
  int n;
  cin>>n>>k;
  set<int> s;
  for(int i=0;i<n;i++)
  {
    int x, r, ind;
    cin>>x>>r>>ind;
    s.insert(x);
    s.insert(x-r);
    s.insert(x+r);
    f[ind].pb(mpr(x,mpr(x-r,x+r)));
  }
  map<int,int> mp;
  for(set<int>::iterator it=s.begin();it!=s.end();it++)
    mp[*it] = len++;
  for(int i=0;i<maxf;i++)
    for(int j=0;j<f[i].size();j++)
    {
      f[i][j].F = mp[f[i][j].F];
      f[i][j].S.F = mp[f[i][j].S.F];
      f[i][j].S.S = mp[f[i][j].S.S];
    }
  ll ans = 0;
  for(int i=0;i<maxf;i++)ans+=solve(i);
  cout<<ans<<endl;
  return 0;
}


#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define pb push_back
#define ff first
#define ss second
void fast() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); }
template<typename T> void print(initializer_list<T> text) {
	for (auto &value: text) {
		cout << value << " ";
	}
	cout << "\n";
}

const int MOD = 1000000007;
const int INF = 1e9;
const long long INFll = INF *1ll* INF;
/*----------------------------------*/

struct item {
	int key, prior, cnt;
	item *l, *r;
	item() {}
	item(int key,int prior): key(key), prior(prior), cnt(1), l(NULL), r(NULL) {}
};
typedef item* pitem;
int cnt(pitem t) {
	return t ? t->cnt : 0;
}
void upd_cnt(pitem t) {
	if(t)
		t->cnt = 1 + cnt(t->l) + cnt(t->r);
}

void split (pitem t,int key, pitem &l, pitem &r) {
	if (!t)
		l = r = NULL;
	else if(key < t->key)
		split(t->l, key, l, t->l), r = t;
	else
		split(t->r, key, t->r, r), l = t;
	upd_cnt(t);
}

void merge (pitem &t, pitem l, pitem r) {
	if (!l || !r)
		t = l ? l : r;
	else if(l->prior > r->prior)
		merge(l->r, l->r, r), t = l ;
	else
		merge(r->l, l, l->r), t = r ;
	upd_cnt(t);
}

void insert(pitem &t, pitem it) {
	if(!t)
		t = it;
	else if(it->prior > t->prior)
		split(t, it->key, it->l, it->r), t = it;
	else
		insert(it->key < t->key ? t->l : t->r, it);
	upd_cnt(t);
}

void erase(pitem &t,int key) {
	if(t->key == key)
		merge(t, t->l, t->r);
	else
		erase(key <= t->key ? t->l : t->r, key);
	upd_cnt(t);
}

void inorder(pitem &t)
{
	if(!t) return;
	inorder(t->l);
	cout<<t->key<<' ';
	inorder(t->r);
}

struct tower{
	int x,r,f;
	bool operator<(tower other) const
	{
		return x < other.x;
	}
};

int main() {

	int n,k; cin>>n>>k;
	long long ans = 0;
	pitem tr[1001];
	for(int i = 0;i<=1000;i++) tr[i] = NULL;
	vector<pair<pair<int,int>, tower> > c;

	for(int i = 0;i<n;i++){
		tower to;
		cin>>to.x>>to.r>>to.f;
		c.pb(mp(mp(to.x-to.r,0),to));
		c.pb(mp(mp(to.x,1)     ,to));
		c.pb(mp(mp(to.x+to.r,2),to));
	}

	sort(c.begin(), c.end());

	map<int,int> m;
	for(auto e: c) {

		int x = e.ss.x,r = e.ss.r,f = e.ss.f;
		//cout<<e.ff.ff<<' '<<e.ff.ss<<' '<<x<<endl;
		if(e.ff.ss == 0) //open
		{
			insert(tr[f], new item(x, rand()%10000) );
			//cout<<"O ";
			//inorder(tr[f]);
			//cout<<endl;
		}
		else if(e.ff.ss==1) //middle
		{
			long long res = 0;
			for(int range = f - k; range <= f + k; range++)
			{
				if(range<1 && range>1000) continue;
				pitem lt, rt, rlt, rrt;
				split(tr[range], x-r, lt, rt);
				split(rt, x+r+1, rlt, rrt);
				res += cnt(rlt);
				merge(rt, rlt, rrt);
				merge(tr[range], lt, rt);
			}
			ans += res-1;
		}
		else //close
		{
			//cout<<"CS "<<x<<"/";
			//inorder(tr[f]);
			//cout<<endl;
			erase(tr[f], x);
			//cout<<"CE ";
			//inorder(tr[f]);
			//cout<<endl;
		}
	}
	cout<<ans/2;
}


#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define pb push_back
#define ff first
#define ss second
void fast() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); }
template<typename T> void print(initializer_list<T> text) {
	for (auto &value: text) {
		cout << value << " ";
	}
	cout << "\n";
}

const int MOD = 1000000007;
const int INF = 1e9;
const long long INFll = INF *1ll* INF;
/*----------------------------------*/

struct item {
	int key, prior, cnt;
	item *l, *r;
	item() {}
	item(int key,int prior): key(key), prior(prior), cnt(1), l(NULL), r(NULL) {}
};
typedef item* pitem;
int cnt(pitem t) {
	return t ? t->cnt : 0;
}
void upd_cnt(pitem t) {
	if(t)
		t->cnt = 1 + cnt(t->l) + cnt(t->r);
}

void split (pitem t,int key, pitem &l, pitem &r) {
	if (!t)
		l = r = NULL;
	else if(key < t->key)
		split(t->l, key, l, t->l), r = t;
	else
		split(t->r, key, t->r, r), l = t;
	upd_cnt(t);
}

void merge (pitem &t, pitem l, pitem r) {
	if (!l || !r)
		t = l ? l : r;
	else if(l->prior > r->prior)
		merge(l->r, l->r, r), t = l ;
	else
		merge(r->l, l, l->r), t = r ;
	upd_cnt(t);
}

void insert(pitem &t, pitem it) {
	if(!t)
		t = it;
	else if(it->prior > t->prior)
		split(t, it->key, it->l, it->r), t = it;
	else
		insert(it->key < t->key ? t->l : t->r, it);
	upd_cnt(t);
}

void erase(pitem &t,int key) {
	if(t->key == key)
		merge(t, t->l, t->r);
	else
		erase(key < t->key ? t->l : t->r, key);
	upd_cnt(t);
}

void inorder(pitem &t)
{
	if(!t) return;
	inorder(t->l);
	cout<<t->key<<' ';
	inorder(t->r);
}

struct tower{
	int x,r,f;
	bool operator<(tower other) const
	{
		return x < other.x;
	}
};

int main() {

	int n,k; cin>>n>>k;
	long long ans = 0;
	pitem tr[1001];
	for(int i = 0;i<=1000;i++) tr[i] = NULL;
	vector<pair<pair<int,int>, tower> > c;

	for(int i = 0;i<n;i++){
		tower to;
		cin>>to.x>>to.r>>to.f;
		c.pb(mp(mp(to.x-to.r,0),to));
		c.pb(mp(mp(to.x,1)     ,to));
		c.pb(mp(mp(to.x+to.r,2),to));
	}

	sort(c.begin(), c.end());

	map<int,int> m;
	for(auto e: c) {

		int x = e.ss.x,r = e.ss.r,f = e.ss.f;
		//cout<<e.ff.ff<<' '<<e.ff.ss<<' '<<x<<endl;
		if(e.ff.ss == 0) //open
		{
			insert(tr[f], new item(x, rand()%10000) );
			//cout<<"O ";
			//inorder(tr[f]);
			//cout<<endl;
		}
		else if(e.ff.ss==1) //middle
		{
			long long res = 0;
			for(int range = f - k; range <= f + k; range++)
			{
				if(range<1 && range>1000) continue;
				pitem lt, rt, rlt, rrt;
				split(tr[range], x-r, lt, rt);
				split(rt, x+r+1, rlt, rrt);
				res += cnt(rlt);
				merge(rt, rlt, rrt);
				merge(tr[range], lt, rt);
			}
			ans += res-1;
		}
		else //close
		{
			//cout<<"CS "<<x<<"/";
			//inorder(tr[f]);
			//cout<<endl;
			if(tr[f])
			erase(tr[f], x);
			//cout<<"CE ";
			//inorder(tr[f]);
			//cout<<endl;
		}
	}
	cout<<ans/2;
}


#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define pb push_back
#define ff first
#define ss second
void fast() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); }
template<typename T> void print(initializer_list<T> text) {
	for (auto &value: text) {
		cout << value << " ";
	}
	cout << "\n";
}

const int MOD = 1000000007;
const int INF = 1e9;
const long long INFll = INF *1ll* INF;
/*----------------------------------*/

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

int getRand(int l, int r)
{
	uniform_int_distribution<int> uid(l, r);
	return uid(rng);
}

struct Treap
{
	struct data
	{
		int priority, val, cnt;
		data *l, *r;

	 	data()
	 	{
	 		val = 0, cnt = 0, l = NULL, r = NULL;
	 	}

		data (int _val)
		{
			val = _val, cnt = 1;
			l = NULL, r = NULL;
			priority = getRand(1, 2e9);
		}
	};

	typedef struct data* node;

	node head;

	Treap(): head(0) {}

	int cnt(node cur)
	{
		return cur ? cur->cnt : 0;
	}

	void updateCnt(node cur)
	{
		if(cur)
			cur->cnt = cnt(cur->l) + cnt(cur->r) + 1;
	}

	void push(node cur) //Lazy Propagation
 	{
		;
	}

	void combine(node &cur, node l, node r)
	{
		if(!l)
		{
			cur = r;
			return;
		}
		if(!r)
		{
			cur = l;
			return;
		}
		//Merge Operations like in segment tree
	}

	void reset(node &cur) //To reset other fields of cur except value and cnt
	{
		if(!cur)
			return;
	}

	void operation(node &cur)
	{
		if(!cur)
			return;
		reset(cur);
		combine(cur, cur->l, cur);
		combine(cur, cur, cur->r);
	}

	void splitPos(node cur, node &l, node &r, int k, int add = 0)
	{
		if(!cur)
			return void(l = r = 0);
		push(cur);
		int idx = add + cnt(cur->l);
		if(idx <= k)
			splitPos(cur->r, cur->r, r, k, idx + 1), l = cur;
		else
			splitPos(cur->l, l, cur->l, k, add), r = cur;
		updateCnt(cur);
		operation(cur);
	}

	void split(node cur, node &l, node &r, int k)
	{
		if(!cur)
			return void(l = r = 0);
		push(cur);
		int idx = cur -> val;
		if(idx <= k)
			split(cur->r, cur->r, r, k), l = cur;
		else
			split(cur->l, l, cur->l, k), r = cur;
		updateCnt(cur);
		operation(cur);
	}

	void merge(node &cur, node l, node r)
	{
		push(l);
		push(r);
		if(!l || !r)
			cur = l ? l : r;
		else if(l->priority > r->priority)
			merge(l->r, l->r, r), cur = l;
		else
			merge(r->l, l, r->l), cur = r;
		updateCnt(cur);
		operation(cur);
	}

	void insert(int val)
	{
		if(!head)
		{
			head = new data(val);
			return;
		}
		node l, r, mid, mid2, rr;
		mid = new data(val);
		split(head, l, r, val - 1);
		merge(l, l, mid);
		split(r, mid2, rr, val);
		merge(head, l, rr);
	}

	void erase(int val)
	{
		node l, r, mid;
		split(head, l, r, val - 1);
		split(r, mid, r, val);
		merge(head, l, r);
	}

	void inorder(node cur)
	{
		if(!cur)
			return;
		push(cur);
		inorder(cur->l);
		cout<<cur->val<<" ";
		inorder(cur->r);
	}

	void inorder()
	{
		inorder(head);
		cout<<endl;
	}

	void clear(node cur)
	{
		if(!cur)
			return;
		clear(cur->l), clear(cur->r);
		delete cur;
	}

	void clear()
	{
		clear(head);
	}

	int find_by_order(int x) //1 indexed
	{
		if(!x)
			return -1;
		x--;
		node l, r, mid;
		splitPos(head, l, r, x - 1);
		splitPos(r, mid, r, 0);
		int ans = -1;
		if(cnt(mid) == 1)
			ans = mid->val;
		merge(r, mid, r);
		merge(head, l, r);
		return ans;
	}

	int order_of_key(int val) //1 indexed
	{
		node l, r, mid;
		split(head, l, r, val - 1);
		split(r, mid, r, val);
		int ans = -1;
		if(cnt(mid) == 1)
			ans = 1 + cnt(l);
		merge(r, mid, r);
		merge(head, l, r);
		return ans;
	}
};

//Problem 1: https://www.spoj.com/problems/ALLIN1/
//Solution 1: http://p.ip.fi/DOgq

struct tower{
	int x,r,f;
	bool operator<(tower other) const
	{
		return x < other.x;
	}
};

int main() {

	int n,k; cin>>n>>k;
	long long ans = 0;
	Treap tr[1001];
	vector<pair<pair<int,int>, tower> > c;

	for(int i = 0;i<n;i++){
		tower to;
		cin>>to.x>>to.r>>to.f;
		c.pb(mp(mp(to.x-to.r,0),to));
		c.pb(mp(mp(to.x,1)     ,to));
		c.pb(mp(mp(to.x+to.r,2),to));
	}

	sort(c.begin(), c.end());

	map<int,int> m;
	for(auto e: c) {

		int x = e.ss.x,r = e.ss.r,f = e.ss.f;
		//cout<<e.ff.ff<<' '<<e.ff.ss<<' '<<x<<endl;
		if(e.ff.ss == 0) //open
		{
			tr[f].insert(x);
			//cout<<"O ";
			//inorder(tr[f]);
			//cout<<endl;
		}
		else if(e.ff.ss==1) //middle
		{
			long long res = 0;
			for(int range = f - k; range <= f + k; range++)
			{
				if(range<1 && range>1000) continue;
				Treap lt, rt, rlt, rrt;
				tr[range].split(tr[range].head, lt.head, rt.head, x-r-1);
				rt.split(rt.head, rlt.head, rrt.head, x+r);
				res += rlt.cnt(rlt.head);
				rt.merge(rt.head, rlt.head, rrt.head);
				tr[range].merge(tr[range].head, lt.head, rt.head);
			}
			ans += res-1;
		}
		else //close
		{
			//cout<<"CS "<<x<<"/";
			//inorder(tr[f]);
			//cout<<endl;
			tr[f].erase(x);
			//cout<<"CE ";
			//inorder(tr[f]);
			//cout<<endl;
		}
	}
	cout<<ans/2;
}


#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define pb push_back
#define ff first
#define ss second
void fast() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); }
template<typename T> void print(initializer_list<T> text) {
	for (auto &value: text) {
		cout << value << " ";
	}
	cout << "\n";
}

const int MOD = 1000000007;
const int INF = 1e9;
const long long INFll = INF *1ll* INF;
/*----------------------------------*/

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

int getRand(int l, int r)
{
	uniform_int_distribution<int> uid(l, r);
	return uid(rng);
}

struct Treap
{
	struct data
	{
		int priority, val, cnt;
		data *l, *r;

	 	data()
	 	{
	 		val = 0, cnt = 0, l = NULL, r = NULL;
	 	}

		data (int _val)
		{
			val = _val, cnt = 1;
			l = NULL, r = NULL;
			priority = getRand(1, 2e9);
		}
	};

	typedef struct data* node;

	node head;

	Treap(): head(0) {}

	int cnt(node cur)
	{
		return cur ? cur->cnt : 0;
	}

	void updateCnt(node cur)
	{
		if(cur)
			cur->cnt = cnt(cur->l) + cnt(cur->r) + 1;
	}

	void push(node cur) //Lazy Propagation
 	{
		;
	}

	void combine(node &cur, node l, node r)
	{
		if(!l)
		{
			cur = r;
			return;
		}
		if(!r)
		{
			cur = l;
			return;
		}
		//Merge Operations like in segment tree
	}

	void reset(node &cur) //To reset other fields of cur except value and cnt
	{
		if(!cur)
			return;
	}

	void operation(node &cur)
	{
		if(!cur)
			return;
		reset(cur);
		combine(cur, cur->l, cur);
		combine(cur, cur, cur->r);
	}

	void splitPos(node cur, node &l, node &r, int k, int add = 0)
	{
		if(!cur)
			return void(l = r = 0);
		push(cur);
		int idx = add + cnt(cur->l);
		if(idx <= k)
			splitPos(cur->r, cur->r, r, k, idx + 1), l = cur;
		else
			splitPos(cur->l, l, cur->l, k, add), r = cur;
		updateCnt(cur);
		operation(cur);
	}

	void split(node cur, node &l, node &r, int k)
	{
		if(!cur)
			return void(l = r = 0);
		push(cur);
		int idx = cur -> val;
		if(idx <= k)
			split(cur->r, cur->r, r, k), l = cur;
		else
			split(cur->l, l, cur->l, k), r = cur;
		updateCnt(cur);
		operation(cur);
	}

	void merge(node &cur, node l, node r)
	{
		push(l);
		push(r);
		if(!l || !r)
			cur = l ? l : r;
		else if(l->priority > r->priority)
			merge(l->r, l->r, r), cur = l;
		else
			merge(r->l, l, r->l), cur = r;
		updateCnt(cur);
		operation(cur);
	}

	void insert(int val)
	{
		if(!head)
		{
			head = new data(val);
			return;
		}
		node l, r, mid, mid2, rr;
		mid = new data(val);
		split(head, l, r, val - 1);
		merge(l, l, mid);
		split(r, mid2, rr, val);
		merge(head, l, rr);
	}

	void erase(int val)
	{
		node l, r, mid;
		split(head, l, r, val - 1);
		split(r, mid, r, val);
		merge(head, l, r);
	}

	void inorder(node cur)
	{
		if(!cur)
			return;
		push(cur);
		inorder(cur->l);
		cout<<cur->val<<" ";
		inorder(cur->r);
	}

	void inorder()
	{
		inorder(head);
		cout<<endl;
	}

	void clear(node cur)
	{
		if(!cur)
			return;
		clear(cur->l), clear(cur->r);
		delete cur;
	}

	void clear()
	{
		clear(head);
	}

	int find_by_order(int x) //1 indexed
	{
		if(!x)
			return -1;
		x--;
		node l, r, mid;
		splitPos(head, l, r, x - 1);
		splitPos(r, mid, r, 0);
		int ans = -1;
		if(cnt(mid) == 1)
			ans = mid->val;
		merge(r, mid, r);
		merge(head, l, r);
		return ans;
	}

	int order_of_key(int val) //1 indexed
	{
		node l, r, mid;
		split(head, l, r, val - 1);
		split(r, mid, r, val);
		int ans = -1;
		if(cnt(mid) == 1)
			ans = 1 + cnt(l);
		merge(r, mid, r);
		merge(head, l, r);
		return ans;
	}
};

//Problem 1: https://www.spoj.com/problems/ALLIN1/
//Solution 1: http://p.ip.fi/DOgq

struct tower{
	int x,r,f;
	bool operator<(tower other) const
	{
		return x < other.x;
	}
};

int main() {

	int n,k; cin>>n>>k;
	long long ans = 0;
	Treap tr[10001];
	vector<pair<pair<int,int>, tower> > c;

	for(int i = 0;i<n;i++){
		tower to;
		cin>>to.x>>to.r>>to.f;
		c.pb(mp(mp(to.x-to.r,0),to));
		c.pb(mp(mp(to.x,1)     ,to));
		c.pb(mp(mp(to.x+to.r,2),to));
	}

	sort(c.begin(), c.end());

	map<int,int> m;
	for(auto e: c) {

		int x = e.ss.x,r = e.ss.r,f = e.ss.f;
		//cout<<e.ff.ff<<' '<<e.ff.ss<<' '<<x<<endl;
		if(e.ff.ss == 0) //open
		{
			tr[f].insert(x);
			//cout<<"O ";
			//inorder(tr[f]);
			//cout<<endl;
		}
		else if(e.ff.ss==1) //middle
		{
			long long res = 0;
			for(int range = f - k; range <= f + k; range++)
			{
				if(range<1 && range>10000) continue;
				Treap lt, rt, rlt, rrt;
				tr[range].split(tr[range].head, lt.head, rt.head, x-r-1);
				rt.split(rt.head, rlt.head, rrt.head, x+r);
				res += rlt.cnt(rlt.head);
				rt.merge(rt.head, rlt.head, rrt.head);
				tr[range].merge(tr[range].head, lt.head, rt.head);
			}
			ans += res-1;
		}
		else //close
		{
			//cout<<"CS "<<x<<"/";
			//inorder(tr[f]);
			//cout<<endl;
			tr[f].erase(x);
			//cout<<"CE ";
			//inorder(tr[f]);
			//cout<<endl;
		}
	}
	cout<<ans/2;
}


#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define pb push_back
#define ff first
#define ss second
void fast() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); }
template<typename T> void print(initializer_list<T> text) {
	for (auto &value: text) {
		cout << value << " ";
	}
	cout << "\n";
}

const int MOD = 1000000007;
const int INF = 1e9;
const long long INFll = INF *1ll* INF;
/*----------------------------------*/

struct item {
	int key, prior, cnt;
	item *l, *r;
	item() {}
	item(int key,int prior): key(key), prior(prior), cnt(1), l(NULL), r(NULL) {}
};
typedef item* pitem;
int cnt(pitem t) {
	return t ? t->cnt : 0;
}
void upd_cnt(pitem t) {
	if(t)
		t->cnt = 1 + cnt(t->l) + cnt(t->r);
}

void split (pitem t,int key, pitem &l, pitem &r) {
	if (!t)
		l = r = NULL;
	else if(key < t->key)
		split(t->l, key, l, t->l), r = t;
	else
		split(t->r, key, t->r, r), l = t;
	upd_cnt(t);
}

void merge (pitem &t, pitem l, pitem r) {
	if (!l || !r)
		t = l ? l : r;
	else if(l->prior > r->prior)
		merge(l->r, l->r, r), t = l ;
	else
		merge(r->l, l, l->r), t = r ;
	upd_cnt(t);
}

void insert(pitem &t, pitem it) {
	if(!t)
		t = it;
	else if(it->prior > t->prior)
		split(t, it->key, it->l, it->r), t = it;
	else
		insert(it->key < t->key ? t->l : t->r, it);
	upd_cnt(t);
}

void erase(pitem &t,int key) {
	if(t->key == key)
		merge(t, t->l, t->r);
	else
		erase(key < t->key ? t->l : t->r, key);
	upd_cnt(t);
}

void inorder(pitem &t)
{
	if(!t) return;
	inorder(t->l);
	cout<<t->key<<' ';
	inorder(t->r);
}

struct tower{
	int x,r,f;
	bool operator<(tower other) const
	{
		return x < other.x;
	}
};

int main() {

	int n,k; cin>>n>>k;
	long long ans = 0;
	pitem tr[1001];
	for(int i = 0;i<=1000;i++) tr[i] = NULL;
	vector<pair<pair<int,int>, tower> > c;

	for(int i = 0;i<n;i++){
		tower to;
		cin>>to.x>>to.r>>to.f;
		c.pb(mp(mp(to.x-to.r,0),to));
		c.pb(mp(mp(to.x,1)     ,to));
		c.pb(mp(mp(to.x+to.r,2),to));
	}

	sort(c.begin(), c.end());

	map<int,int> m;
	for(auto e: c) {

		int x = e.ss.x,r = e.ss.r,f = e.ss.f;
		//cout<<e.ff.ff<<' '<<e.ff.ss<<' '<<x<<endl;
		if(e.ff.ss == 0) //open
		{
			insert(tr[f], new item(x, rand()%10000) );
			//cout<<"O ";
			//inorder(tr[f]);
			//cout<<endl;
		}
		else if(e.ff.ss==1) //middle
		{
			long long res = 0;
			for(int range = f - k; range <= f + k; range++)
			{
				if(range<1 && range>1000) continue;
				pitem lt, rt, rlt, rrt;
				split(tr[range], x-r, lt, rt);
				split(rt, x+r+1, rlt, rrt);
				res += cnt(rlt);
				merge(rt, rlt, rrt);
				merge(tr[range], lt, rt);
			}
			ans += res-1;
		}
		else //close
		{
			//cout<<"CS "<<x<<"/";
			//inorder(tr[f]);
			//cout<<endl;
			erase(tr[f], x);
			//cout<<"CE ";
			//inorder(tr[f]);
			//cout<<endl;
		}
	}
	cout<<ans/2;
}


#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define pb push_back
#define ff first
#define ss second
void fast() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); }
template<typename T> void print(initializer_list<T> text) {
	for (auto &value: text) {
		cout << value << " ";
	}
	cout << "\n";
}

const int MOD = 1000000007;
const int INF = 1e9;
const long long INFll = INF *1ll* INF;
/*----------------------------------*/

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

int getRand(int l, int r)
{
	uniform_int_distribution<int> uid(l, r);
	return uid(rng);
}

struct Treap
{
	struct data
	{
		int priority, val, cnt;
		data *l, *r;

	 	data()
	 	{
	 		val = 0, cnt = 0, l = NULL, r = NULL;
	 	}

		data (int _val)
		{
			val = _val, cnt = 1;
			l = NULL, r = NULL;
			priority = getRand(1, 2e9);
		}
	};

	typedef struct data* node;

	node head;

	Treap(): head(0) {}

	int cnt(node cur)
	{
		return cur ? cur->cnt : 0;
	}

	void updateCnt(node cur)
	{
		if(cur)
			cur->cnt = cnt(cur->l) + cnt(cur->r) + 1;
	}

	void push(node cur) //Lazy Propagation
 	{
		;
	}

	void combine(node &cur, node l, node r)
	{
		if(!l)
		{
			cur = r;
			return;
		}
		if(!r)
		{
			cur = l;
			return;
		}
		//Merge Operations like in segment tree
	}

	void reset(node &cur) //To reset other fields of cur except value and cnt
	{
		if(!cur)
			return;
	}

	void operation(node &cur)
	{
		if(!cur)
			return;
		reset(cur);
		combine(cur, cur->l, cur);
		combine(cur, cur, cur->r);
	}

	void splitPos(node cur, node &l, node &r, int k, int add = 0)
	{
		if(!cur)
			return void(l = r = 0);
		push(cur);
		int idx = add + cnt(cur->l);
		if(idx <= k)
			splitPos(cur->r, cur->r, r, k, idx + 1), l = cur;
		else
			splitPos(cur->l, l, cur->l, k, add), r = cur;
		updateCnt(cur);
		operation(cur);
	}

	void split(node cur, node &l, node &r, int k)
	{
		if(!cur)
			return void(l = r = 0);
		push(cur);
		int idx = cur -> val;
		if(idx <= k)
			split(cur->r, cur->r, r, k), l = cur;
		else
			split(cur->l, l, cur->l, k), r = cur;
		updateCnt(cur);
		operation(cur);
	}

	void merge(node &cur, node l, node r)
	{
		push(l);
		push(r);
		if(!l || !r)
			cur = l ? l : r;
		else if(l->priority > r->priority)
			merge(l->r, l->r, r), cur = l;
		else
			merge(r->l, l, r->l), cur = r;
		updateCnt(cur);
		operation(cur);
	}

	void insert(int val)
	{
		if(!head)
		{
			head = new data(val);
			return;
		}
		node l, r, mid, mid2, rr;
		mid = new data(val);
		split(head, l, r, val - 1);
		merge(l, l, mid);
		split(r, mid2, rr, val);
		merge(head, l, rr);
	}

	void erase(int val)
	{
		node l, r, mid;
		split(head, l, r, val - 1);
		split(r, mid, r, val);
		merge(head, l, r);
	}

	void inorder(node cur)
	{
		if(!cur)
			return;
		push(cur);
		inorder(cur->l);
		cout<<cur->val<<" ";
		inorder(cur->r);
	}

	void inorder()
	{
		inorder(head);
		cout<<endl;
	}

	void clear(node cur)
	{
		if(!cur)
			return;
		clear(cur->l), clear(cur->r);
		delete cur;
	}

	void clear()
	{
		clear(head);
	}

	int find_by_order(int x) //1 indexed
	{
		if(!x)
			return -1;
		x--;
		node l, r, mid;
		splitPos(head, l, r, x - 1);
		splitPos(r, mid, r, 0);
		int ans = -1;
		if(cnt(mid) == 1)
			ans = mid->val;
		merge(r, mid, r);
		merge(head, l, r);
		return ans;
	}

	int order_of_key(int val) //1 indexed
	{
		node l, r, mid;
		split(head, l, r, val - 1);
		split(r, mid, r, val);
		int ans = -1;
		if(cnt(mid) == 1)
			ans = 1 + cnt(l);
		merge(r, mid, r);
		merge(head, l, r);
		return ans;
	}
};

//Problem 1: https://www.spoj.com/problems/ALLIN1/
//Solution 1: http://p.ip.fi/DOgq

struct tower{
	int x,r,f;
	bool operator<(tower other) const
	{
		return x < other.x;
	}
};

int main() {

	int n,k; cin>>n>>k;
	long long ans = 0;
	Treap tr[10001];
	vector<pair<pair<int,int>, tower> > c;

	for(int i = 0;i<n;i++){
		tower to;
		cin>>to.x>>to.r>>to.f;
		c.pb(mp(mp(to.x-to.r,0),to));
		c.pb(mp(mp(to.x,1)     ,to));
		c.pb(mp(mp(to.x+to.r,2),to));
	}

	sort(c.begin(), c.end());

	map<int,int> m;
	for(auto e: c) {

		int x = e.ss.x,r = e.ss.r,f = e.ss.f;
		//cout<<e.ff.ff<<' '<<e.ff.ss<<' '<<x<<endl;
		if(e.ff.ss == 0) //open
		{
			tr[f].insert(x);
			//cout<<"O ";
			//inorder(tr[f]);
			//cout<<endl;
		}
		else if(e.ff.ss==1) //middle
		{
			long long res = 0;
			for(int range = f - k; range <= f + k; range++)
			{
				if(range<1 && range>1000) continue;
				Treap lt, rt, rlt, rrt;
				tr[range].split(tr[range].head, lt.head, rt.head, x-r-1);
				rt.split(rt.head, rlt.head, rrt.head, x+r);
				res += rlt.cnt(rlt.head);
				rt.merge(rt.head, rlt.head, rrt.head);
				tr[range].merge(tr[range].head, lt.head, rt.head);
			}
			ans += res-1;
		}
		else //close
		{
			//cout<<"CS "<<x<<"/";
			//inorder(tr[f]);
			//cout<<endl;
			tr[f].erase(x);
			//cout<<"CE ";
			//inorder(tr[f]);
			//cout<<endl;
		}
	}
	cout<<ans/2;
}


#include<bits/stdc++.h>
using namespace std;
#define mp make_pair
#define pb push_back
#define ff first
#define ss second
void fast() { ios_base::sync_with_stdio(false); cin.tie(NULL); cout.tie(NULL); }
template<typename T> void print(initializer_list<T> text) {
	for (auto &value: text) {
		cout << value << " ";
	}
	cout << "\n";
}

const int MOD = 1000000007;
const int INF = 1e9;
const long long INFll = INF *1ll* INF;
/*----------------------------------*/

mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());

int getRand(int l, int r)
{
	uniform_int_distribution<int> uid(l, r);
	return uid(rng);
}

struct Treap
{
	struct data
	{
		int priority, val, cnt;
		data *l, *r;

	 	data()
	 	{
	 		val = 0, cnt = 0, l = NULL, r = NULL;
	 	}

		data (int _val)
		{
			val = _val, cnt = 1;
			l = NULL, r = NULL;
			priority = getRand(1, 2e9);
		}
	};

	typedef struct data* node;

	node head;

	Treap(): head(0) {}

	int cnt(node cur)
	{
		return cur ? cur->cnt : 0;
	}

	void updateCnt(node cur)
	{
		if(cur)
			cur->cnt = cnt(cur->l) + cnt(cur->r) + 1;
	}

	void push(node cur) //Lazy Propagation
 	{
		;
	}

	void combine(node &cur, node l, node r)
	{
		if(!l)
		{
			cur = r;
			return;
		}
		if(!r)
		{
			cur = l;
			return;
		}
		//Merge Operations like in segment tree
	}

	void reset(node &cur) //To reset other fields of cur except value and cnt
	{
		if(!cur)
			return;
	}

	void operation(node &cur)
	{
		if(!cur)
			return;
		reset(cur);
		combine(cur, cur->l, cur);
		combine(cur, cur, cur->r);
	}

	void splitPos(node cur, node &l, node &r, int k, int add = 0)
	{
		if(!cur)
			return void(l = r = 0);
		push(cur);
		int idx = add + cnt(cur->l);
		if(idx <= k)
			splitPos(cur->r, cur->r, r, k, idx + 1), l = cur;
		else
			splitPos(cur->l, l, cur->l, k, add), r = cur;
		updateCnt(cur);
		operation(cur);
	}

	void split(node cur, node &l, node &r, int k)
	{
		if(!cur)
			return void(l = r = 0);
		push(cur);
		int idx = cur -> val;
		if(idx <= k)
			split(cur->r, cur->r, r, k), l = cur;
		else
			split(cur->l, l, cur->l, k), r = cur;
		updateCnt(cur);
		operation(cur);
	}

	void merge(node &cur, node l, node r)
	{
		push(l);
		push(r);
		if(!l || !r)
			cur = l ? l : r;
		else if(l->priority > r->priority)
			merge(l->r, l->r, r), cur = l;
		else
			merge(r->l, l, r->l), cur = r;
		updateCnt(cur);
		operation(cur);
	}

	void insert(int val)
	{
		if(!head)
		{
			head = new data(val);
			return;
		}
		node l, r, mid, mid2, rr;
		mid = new data(val);
		split(head, l, r, val - 1);
		merge(l, l, mid);
		split(r, mid2, rr, val);
		merge(head, l, rr);
	}

	void erase(int val)
	{
		node l, r, mid;
		split(head, l, r, val - 1);
		split(r, mid, r, val);
		merge(head, l, r);
	}

	void inorder(node cur)
	{
		if(!cur)
			return;
		push(cur);
		inorder(cur->l);
		cout<<cur->val<<" ";
		inorder(cur->r);
	}

	void inorder()
	{
		inorder(head);
		cout<<endl;
	}

	void clear(node cur)
	{
		if(!cur)
			return;
		clear(cur->l), clear(cur->r);
		delete cur;
	}

	void clear()
	{
		clear(head);
	}

	int find_by_order(int x) //1 indexed
	{
		if(!x)
			return -1;
		x--;
		node l, r, mid;
		splitPos(head, l, r, x - 1);
		splitPos(r, mid, r, 0);
		int ans = -1;
		if(cnt(mid) == 1)
			ans = mid->val;
		merge(r, mid, r);
		merge(head, l, r);
		return ans;
	}

	int order_of_key(int val) //1 indexed
	{
		node l, r, mid;
		split(head, l, r, val - 1);
		split(r, mid, r, val);
		int ans = -1;
		if(cnt(mid) == 1)
			ans = 1 + cnt(l);
		merge(r, mid, r);
		merge(head, l, r);
		return ans;
	}
};

//Problem 1: https://www.spoj.com/problems/ALLIN1/
//Solution 1: http://p.ip.fi/DOgq

struct tower{
	int x,r,f;
	bool operator<(tower other) const
	{
		return x < other.x;
	}
};

int main() {

	int n,k; cin>>n>>k;
	long long ans = 0;
	Treap tr[10001];
	vector<pair<pair<int,int>, tower> > c;

	for(int i = 0;i<n;i++){
		tower to;
		cin>>to.x>>to.r>>to.f;
		c.pb(mp(mp(to.x-to.r,0),to));
		c.pb(mp(mp(to.x,1)     ,to));
		c.pb(mp(mp(to.x+to.r,2),to));
	}

	sort(c.begin(), c.end());

	map<int,int> m;
	for(auto e: c) {

		int x = e.ss.x,r = e.ss.r,f = e.ss.f;
		//cout<<e.ff.ff<<' '<<e.ff.ss<<' '<<x<<endl;
		if(e.ff.ss == 0) //open
		{
			tr[f].insert(x);
			//cout<<"O ";
			//inorder(tr[f]);
			//cout<<endl;
		}
		else if(e.ff.ss==1) //middle
		{
			long long res = 0;
			for(int range = f - k; range <= f + k; range++)
			{
				if(range<1 || range>10000) continue;
				Treap lt, rt, rlt, rrt;
				tr[range].split(tr[range].head, lt.head, rt.head, x-r-1);
				rt.split(rt.head, rlt.head, rrt.head, x+r);
				res += rlt.cnt(rlt.head);
				rt.merge(rt.head, rlt.head, rrt.head);
				tr[range].merge(tr[range].head, lt.head, rt.head);
			}
			ans += res-1;
		}
		else //close
		{
			//cout<<"CS "<<x<<"/";
			//inorder(tr[f]);
			//cout<<endl;
			tr[f].erase(x);
			//cout<<"CE ";
			//inorder(tr[f]);
			//cout<<endl;
		}
	}
	cout<<ans/2;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

struct node
{
    int sum;
    node *l;
    node *r;

    node () : sum(0),l(0),r(0) {}
};

struct tacka
{
   int x,r,f;
   bool operator < (const tacka& b) const{
       return r > b.r;
   }
};

node* ubaci(node* x,ll xl,ll xr,ll p)
{
    if(!x) x = new node;
    x->sum++;
    if(xl==xr) return x;
    ll xm = (xl+xr) >> 1;
    if(p<=xm) x->l = ubaci(x->l,xl,xm,p);
    else x->r=ubaci(x->r,xm+1,xr,p);
}

int getsum(node *x,ll l,ll r,ll xl,ll xr)
{
    if(!x || r < xl || xr < l) return 0;
    if(l<=xl && xr<=r) return x->sum;
    ll xm = (xr+xl) >> 1;
    return getsum(x->l,l,r,xl,xm) + getsum(x->r,l,r,xm+1,xr);
}

int n,k;
node *drva[11005];
tacka a[100005];

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cerr.tie(0);

	cin >> n >> k;

	for(int i=0;i<n;i++)
	{
	    cin >> a[i].x >> a[i].r >> a[i].f;
	    a[i].f+=15;
	}

	sort(a,a+n);
	ll sol=0;

	for(int i=0;i<n;i++)
	{
	    int xx = a[i].x;
	    int rr = a[i].r;
	    int ff = a[i].f;
	    for(int f2=ff-k;f2<=ff+k;f2++)
	    {
	        sol+=getsum(drva[f2],xx-rr,xx+rr,1,1e9);
	    }
	    drva[ff] = ubaci(drva[ff],1,1e9,xx);
	}

	cout << sol;

	return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

struct node
{
    int sum;
    node *l;
    node *r;

    node () : sum(0),l(0),r(0) {}
};

struct tacka
{
   int x,r,f;
   bool operator < (const tacka& b) const{
       return r > b.r;
   }
};

node* ubaci(node* x,ll xl,ll xr,ll p)
{
    if(!x) x = new node;
    x->sum++;
    if(xl==xr) return x;
    ll xm = (xl+xr) >> 1;
    if(p<=xm) x->l = ubaci(x->l,xl,xm,p);
    else x->r=ubaci(x->r,xm+1,xr,p);

    return x;
}

int getsum(node *x,ll l,ll r,ll xl,ll xr)
{
    if(!x || r < xl || xr < l) return 0;
    if(l<=xl && xr<=r) return x->sum;
    ll xm = (xr+xl) >> 1;
    return getsum(x->l,l,r,xl,xm) + getsum(x->r,l,r,xm+1,xr);
}

int n,k;
node *drva[11005];
tacka a[100005];

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cerr.tie(0);

	cin >> n >> k;

	for(int i=0;i<n;i++)
	{
	    cin >> a[i].x >> a[i].r >> a[i].f;
	    a[i].f+=15;
	}

	sort(a,a+n);
	ll sol=0;

	for(int i=0;i<n;i++)
	{
	    auto [xx,rr,ff] = a[i];
	    for(int f2=ff-k;f2<=ff+k;f2++)
	    {
	        sol+=getsum(drva[f2],xx-rr,xx+rr,1,1e9);
	    }
	    drva[ff] = ubaci(drva[ff],1,1e9,xx);
	}

	return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

struct node
{
    int sum;
    node *l;
    node *r;

    node () : sum(0),l(0),r(0) {}
};

struct tacka
{
   int x,r,f;
   bool operator < (const tacka& b) const{
       return r > b.r;
   }
};

node* ubaci(node* x,ll xl,ll xr,ll p)
{
    if(!x) x = new node;
    x->sum++;
    if(xl==xr) return x;
    ll xm = (xl+xr) >> 1;
    if(p<=xm) x->l = ubaci(x->l,xl,xm,p);
    else x->r=ubaci(x->r,xm+1,xr,p);
}

int getsum(node *x,ll l,ll r,ll xl,ll xr)
{
    if(!x || r < xl || xr < l) return 0;
    if(l<=xl && xr<=r) return x->sum;
    ll xm = (xr+xl) >> 1;
    return getsum(x->l,l,r,xl,xm) + getsum(x->r,l,r,xm+1,xr);
}

int n,k;
node *drva[11005];
tacka a[100005];

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cerr.tie(0);

	cin >> n >> k;

	for(int i=1;i<=n;i++)
	{
	    cin >> a[i].x >> a[i].r >> a[i].f;
	    a[i].f+=15;
	}

	sort(a+1,a+n+1);
	ll sol=0;

	for(int i=1;i<=n;i++)
	{
	    auto [xx,rr,ff] = a[i];
	    for(int f2=ff-k;f2<=ff+k;f2++)
	    {
	        sol+=getsum(drva[f2],xx-rr,xx+rr,1,1e9);
	    }
	    drva[ff] = ubaci(drva[ff],1,1e9,xx);
	}

	return 0;
}


#include <bits/stdc++.h>

using namespace std;

typedef long long ll;

struct node
{
    int sum;
    node *l;
    node *r;

    node () : sum(0),l(0),r(0) {}
};

struct tacka
{
   int x,r,f;
   bool operator < (const tacka& b) const{
       return r > b.r;
   }
};

node* ubaci(node* x,ll xl,ll xr,ll p)
{
    if(!x) x = new node;
    x->sum++;
    if(xl==xr) return x;
    ll xm = (xl+xr) >> 1;
    if(p<=xm) x->l = ubaci(x->l,xl,xm,p);
    else x->r=ubaci(x->r,xm+1,xr,p);

    return x;
}

int getsum(node *x,ll l,ll r,ll xl,ll xr)
{
    if(!x || r < xl || xr < l) return 0;
    if(l<=xl && xr<=r) return x->sum;
    ll xm = (xr+xl) >> 1;
    return getsum(x->l,l,r,xl,xm) + getsum(x->r,l,r,xm+1,xr);
}

int n,k;
node *drva[11005];
tacka a[100005];

int main()
{
	ios_base::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cerr.tie(0);

	cin >> n >> k;

	for(int i=0;i<n;i++)
	{
	    cin >> a[i].x >> a[i].r >> a[i].f;
	    a[i].f+=15;
	}

	sort(a,a+n);
	ll sol=0;

	for(int i=0;i<n;i++)
	{
	    int xx = a[i].x;
	    int rr = a[i].r;
	    int ff = a[i].f;
	    for(int f2=ff-k;f2<=ff+k;f2++)
	    {
	        sol+=getsum(drva[f2],xx-rr,xx+rr,1,1e9);
	    }
	    drva[ff] = ubaci(drva[ff],1,1e9,xx);
	}

	cout << sol;

	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

struct _r
{
    int x, r, f;
};

vector<_r> a;
vector<int> t[11000], v[11000];

bool cmp1(_r i, _r j)
{
    return i.x < j.x;
}

bool cmp2(_r i, _r j)
{
    return i.r > j.r;
}

int get(int f, int p)
{
    int res = 0;
    for (int i = p; i >= 0; i = (i&(i+1)) - 1)
        res += t[f][i];
    return res;
}

void modify(int f, int p)
{
    for (int i = p; i < t[f].size(); i |= i+1)
        t[f][i]++;
}

int main()
{
    int n, k, i, j, ans = 0;
    cin >> n >> k;
    a.resize(n);
    for (i = 0; i < n; i++)
        cin >> a[i].x >> a[i].r >> a[i].f;
    sort(a.begin(), a.end(), cmp1);
    for (i = 0; i < n; i++)
        v[a[i].f].push_back(a[i].x);
    for (i = 0; i <= 10000; i++)
        t[i].resize(v[i].size()+3);
    sort(a.begin(), a.end(), cmp2);
    for (i = 0; i < n; i++)
    {
        for (j = max(1, a[i].f - k); j <= min(10000, a[i].f + k); j++)
        {
            int r = upper_bound(v[j].begin(), v[j].end(), a[i].x + a[i].r) - v[j].begin();
            int l = lower_bound(v[j].begin(), v[j].end(), a[i].x - a[i].r) - v[j].begin();
            r--;
            if (r >= l)
                ans += get(j, r) - get(j, l-1);
        }
        modify(a[i].f, lower_bound(v[a[i].f].begin(), v[a[i].f].end(), a[i].x) - v[a[i].f].begin());
    }
    cout << ans;
}


#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

struct _r
{
    int x, r, f;
};

vector<_r> a;
vector<int> t[11000], v[11000];

bool cmp1(_r i, _r j)
{
    return i.x < j.x;
}

bool cmp2(_r i, _r j)
{
    return i.r > j.r;
}

int get(int f, int p)
{
    int res = 0;
    for (int i = p; i >= 0; i = (i&(i+1)) - 1)
        res += t[f][i];
    return res;
}

void modify(int f, int p)
{
    for (int i = p; i < v[f].size(); i |= i+1)
        t[f][i]++;
}

int main()
{
    int n, k, i, j, ans = 0;
    cin >> n >> k;
    a.resize(n);
    for (i = 0; i < n; i++)
        cin >> a[i].x >> a[i].r >> a[i].f;
    sort(a.begin(), a.end(), cmp1);
    for (i = 0; i < n; i++)
        v[a[i].f].push_back(a[i].x);
    for (i = 0; i <= 1000; i++)
        t[i].resize(v[i].size()+3);
    sort(a.begin(), a.end(), cmp2);
    for (i = 0; i < n; i++)
    {
        for (j = max(1, a[i].f - k); j <= min(1000, a[i].f + k); j++)
        {
            int r = upper_bound(v[j].begin(), v[j].end(), a[i].x + a[i].r) - v[j].begin();
            int l = lower_bound(v[j].begin(), v[j].end(), a[i].x - a[i].r) - v[j].begin();
            r--;
            if (r >= l)
                ans += get(j, r) - get(j, l-1);
        }
        modify(a[i].f, lower_bound(v[a[i].f].begin(), v[a[i].f].end(), a[i].x) - v[a[i].f].begin());
    }
    cout << ans;
}


#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

struct _r
{
    int x, r, f;
};

vector<_r> a;
vector<int> t[11000], v[11000];

bool cmp1(_r i, _r j)
{
    return i.x < j.x;
}

bool cmp2(_r i, _r j)
{
    return i.r > j.r;
}

int get(int f, int p)
{
    int res = 0;
    for (int i = p; i >= 0; i = (i&(i+1)) - 1)
        res += t[f][i];
    return res;
}

void modify(int f, int p)
{
    for (int i = p; i < t[f].size(); i |= i+1)
        t[f][i]++;
}

int main()
{
    int n, k, i, j, ans = 0;
    cin >> n >> k;
    a.resize(n);
    for (i = 0; i < n; i++)
        cin >> a[i].x >> a[i].r >> a[i].f;
    sort(a.begin(), a.end(), cmp1);
    for (i = 0; i < n; i++)
        v[a[i].f].push_back(a[i].x);
    for (i = 0; i <= 1000; i++)
        t[i].resize(v[i].size()+3);
    sort(a.begin(), a.end(), cmp2);
    for (i = 0; i < n; i++)
    {
        for (j = max(1, a[i].f - k); j <= min(1000, a[i].f + k); j++)
        {
            int r = upper_bound(v[j].begin(), v[j].end(), a[i].x + a[i].r) - v[j].begin();
            int l = lower_bound(v[j].begin(), v[j].end(), a[i].x - a[i].r) - v[j].begin();
            r--;
            if (r >= l)
                ans += get(j, r) - get(j, l-1);
        }
        modify(a[i].f, lower_bound(v[a[i].f].begin(), v[a[i].f].end(), a[i].x) - v[a[i].f].begin());
    }
    cout << ans;
}


#include <iostream>
#include <vector>
#include <algorithm>

using namespace std;

struct _r
{
    int x, r, f;
};

vector<_r> a;
vector<int> t[11000], v[11000];

bool cmp1(_r i, _r j)
{
    return i.x < j.x;
}

bool cmp2(_r i, _r j)
{
    return i.r > j.r;
}

int get(int f, int p)
{
    int res = 0;
    for (int i = p; i >= 0; i = (i&(i+1)) - 1)
        res += t[f][i];
    return res;
}

void modify(int f, int p)
{
    for (int i = p; i < t[f].size(); i |= i+1)
        t[f][i]++;
}

int main()
{
    ios_base::sync_with_stdio(false);
    int n, k, i, j;
    long long ans = 0;
    cin >> n >> k;
    a.resize(n);
    for (i = 0; i < n; i++)
        cin >> a[i].x >> a[i].r >> a[i].f;
    sort(a.begin(), a.end(), cmp1);
    for (i = 0; i < n; i++)
        v[a[i].f].push_back(a[i].x);
    for (i = 0; i <= 10000; i++)
        t[i].resize(v[i].size()+3);
    sort(a.begin(), a.end(), cmp2);
    for (i = 0; i < n; i++)
    {
        for (j = max(1, a[i].f - k); j <= min(10000, a[i].f + k); j++)
        {
            int r = upper_bound(v[j].begin(), v[j].end(), a[i].x + a[i].r) - v[j].begin();
            int l = lower_bound(v[j].begin(), v[j].end(), a[i].x - a[i].r) - v[j].begin();
            r--;
            if (r >= l)
                ans += get(j, r) - get(j, l-1);
        }
        modify(a[i].f, lower_bound(v[a[i].f].begin(), v[a[i].f].end(), a[i].x) - v[a[i].f].begin());
    }
    cout << ans;
}


// 762E
#include <bits/stdc++.h>
using namespace std;

const int maxn = 1000010;
const int maxf = 10010;
typedef long long LL;

struct radio {
    LL x,r,f;
} a[maxn];
LL n,k;
vector<LL> d[maxf];
LL ans;

bool comp(radio a,radio b){
    return a.r>b.r;
}
void luan(){
    cin>>n>>k;
    for (LL i=1;i<=n;i++){
        cin>>a[i].x>>a[i].r>>a[i].f;
    }
    sort(a+1,a+n+1,comp);
    for (LL i=1,t;i<=n;i++){
        t=a[i].f;
        for (LL j=max(1ll,t-k);j<=t+k;j++){
            ans+=(
                upper_bound(d[j].begin(),d[j].end(),a[i].x+a[i].r)-
                lower_bound(d[j].begin(),d[j].end(),a[i].x-a[i].r)
            );
        }
        d[t].insert(upper_bound(d[t].begin(),d[t].end(),a[i].x),a[i].x);
    }
    cout<<ans;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    luan();
    return 0;
}


// 762E
#include <bits/stdc++.h>
using namespace std;

const int maxn = 1000010;
const int maxf = 10010;
typedef long long LL;

struct radio {
    LL x,r;f;
} a[maxn];
LL n,k;
vector<LL> d[maxf];
LL ans;

bool comp(radio a,radio b){
    return a.r>b.r;
}
void luan(){
    cin>>n>>k;
    for (LL i=1;i<=n;i++){
        cin>>a[i].x>>a[i].r>>a[i].f;
    }
    sort(a+1,a+n+1,comp);
    for (LL i=1,t;i<=n;i++){
        t=a[i].f;
        for (LL j=max(1,t-k);j<=t+k;j++){
            ans+=(
                upper_bound(d[j].begin(),d[j].end(),a[i].x+a[i].r)-
                lower_bound(d[j].begin(),d[j].end(),a[i].x-a[i].r)
            );
        }
        d[t].insert(upper_bound(d[t].begin(),d[t].end(),a[i].x),a[i].x);
    }
    cout<<ans;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    luan();
    return 0;
}


// 762E
#include <bits/stdc++.h>
using namespace std;

const int maxn = 1000010;
const int maxf = 10010;
typedef long long LL;

struct radio {
    LL x,r;
    int f;
} a[maxn];
int n,k;
vector<LL> d[maxf];
LL ans;

bool comp(radio a,radio b){
    return a.r>b.r;
}
void luan(){
    cin>>n>>k;
    for (int i=1;i<=n;i++){
        cin>>a[i].x>>a[i].r>>a[i].f;
    }
    sort(a+1,a+n+1,comp);
    for (int i=1,t;i<=n;i++){
        t=a[i].f;
        for (int j=max(1,t-k);j<=t+k;j++){
            ans+=(
                upper_bound(d[j].begin(),d[j].end(),a[i].x+a[i].r)-
                lower_bound(d[j].begin(),d[j].end(),a[i].x-a[i].r)
            );
        }
        d[t].insert(upper_bound(d[t].begin(),d[t].end(),a[i].x),a[i].x);
    }
    cout<<ans;
}
int main(){
    ios::sync_with_stdio(0);
    cin.tie(0); cout.tie(0);
    luan();
    return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define oo 2000000000
const int N = 10010;
int n , k;
vector< pair<int,int> > f[N];
vector< vector<int> > seg[N];

void merge(vector<int> &v1,vector<int> &v2,vector<int> &v3){
	int j = 0;
	for(int i=0;i<v2.size();i++){
		while(j < v3.size() && v3[j] < v2[i]) v1.push_back(v3[j++]);
		v1.push_back(v2[i]);
	}
	while(j < v3.size()) v1.push_back(v3[j++]);
}

void build(int s,int e,int idx,int cur){
	if(s == e){
		seg[cur][idx].push_back(f[cur][s].second);
		return ;
	}
	build(s,(s+e)/2,idx*2,cur);
	build((s+e)/2+1,e,idx*2+1,cur);
	merge(seg[cur][idx],seg[cur][idx*2],seg[cur][idx*2+1]);
}

int getsum(int s,int e,int idx,int l,int r,int cur,int val){
	if(s > r || e < l) return 0;
	if(s >= l && e <= r) return seg[cur][idx].end() - upper_bound(seg[cur][idx].begin(),seg[cur][idx].end(),val);
	return getsum(s,(s+e)/2,idx*2,l,r,cur,val) + getsum((s+e)/2+1,e,idx*2+1,l,r,cur,val);
}

int getsum2(int s,int e,int idx,int l,int r,int cur,int val){
	if(s > r || e < l) return 0;
	if(s >= l && e <= r) return seg[cur][idx].end() - lower_bound(seg[cur][idx].begin(),seg[cur][idx].end(),val);
	return getsum2(s,(s+e)/2,idx*2,l,r,cur,val) + getsum2((s+e)/2+1,e,idx*2+1,l,r,cur,val);
}

int main() {
	//freopen("in.txt","r",stdin);
	scanf("%d%d",&n,&k);
	for(int i=0;i<n;i++){
		int a, b, c;
		scanf("%d%d%d",&a,&b,&c);
		f[c].push_back(make_pair(a,b));
	}
	for(int i=0;i<N;i++){
		if(f[i].size() == 0) continue;
		sort(f[i].begin(),f[i].end());
		seg[i].resize(4*f[i].size());
		build(0,f[i].size()-1,1,i);
	}
	long long ans = 0 ;
	for(int i=0;i<N;i++){
		for(int j=0;j<f[i].size();j++){
			for(int l=max(1,i-k);l<=i+k;l++){
				if(i == l) continue;
				if(f[l].size() == 0) continue;
				int L = lower_bound(f[l].begin(),f[l].end(),make_pair(f[i][j].first-f[i][j].second,0)) - f[l].begin();
				int r = upper_bound(f[l].begin(),f[l].end(),make_pair(f[i][j].first+f[i][j].second,oo)) - f[l].begin() - 1;
				if(r < L) continue;
				if(l > i)
					ans += getsum(0,f[l].size()-1,1,L,r,l,f[i][j].second);
				else
					ans += getsum2(0,f[l].size()-1,1,L,r,l,f[i][j].second);
			}
			if(j > 0){
				int idx = lower_bound(f[i].begin(),f[i].end(),make_pair(f[i][j].first-f[i][j].second,0)) - f[i].begin();
				if(idx < j)
					ans += getsum2(0,f[i].size()-1,1,idx,j-1,i,f[i][j].second);
				int idx2 = upper_bound(f[i].begin(),f[i].end(),make_pair(f[i][j].first+f[i][j].second,oo)) - f[i].begin() - 1;
				if(idx <= idx2)
					ans += getsum(0,f[i].size()-1,1,idx,idx2,i,f[i][j].second);
			}
		}
	}
	cout << ans << endl;
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define oo 2000000000
const int N = 10010;
int n , k;
vector< pair<int,int> > f[N];
vector< vector<int> > seg[N];

void merge(vector<int> &v1,vector<int> &v2,vector<int> &v3){
	int j = 0;
	for(int i=0;i<v2.size();i++){
		while(j < v3.size() && v3[j] < v2[i]) v1.push_back(v3[j++]);
		v1.push_back(v2[i]);
	}
	while(j < v3.size()) v1.push_back(v3[j++]);
}

void build(int s,int e,int idx,int cur){
	if(s == e){
		seg[cur][idx].push_back(f[cur][s].second);
		return ;
	}
	build(s,(s+e)/2,idx*2,cur);
	build((s+e)/2+1,e,idx*2+1,cur);
	merge(seg[cur][idx],seg[cur][idx*2],seg[cur][idx*2+1]);
}

int getsum(int s,int e,int idx,int l,int r,int cur,int val){
	if(s > r || e < l) return 0;
	if(s >= l && e <= r) return seg[cur][idx].end() - upper_bound(seg[cur][idx].begin(),seg[cur][idx].end(),val);
	return getsum(s,(s+e)/2,idx*2,l,r,cur,val) + getsum((s+e)/2+1,e,idx*2+1,l,r,cur,val);
}

int getsum2(int s,int e,int idx,int l,int r,int cur,int val){
	if(s > r || e < l) return 0;
	if(s >= l && e <= r) return seg[cur][idx].end() - lower_bound(seg[cur][idx].begin(),seg[cur][idx].end(),val);
	return getsum2(s,(s+e)/2,idx*2,l,r,cur,val) + getsum2((s+e)/2+1,e,idx*2+1,l,r,cur,val);
}

int getsum3(int s,int e,int idx,int l,int r,int cur,int val){
	if(s > r || e < l) return 0;
	if(s >= l && e <= r) return upper_bound(seg[cur][idx].begin(),seg[cur][idx].end(),val) - lower_bound(seg[cur][idx].begin(),seg[cur][idx].end(),val);
	return getsum2(s,(s+e)/2,idx*2,l,r,cur,val) + getsum2((s+e)/2+1,e,idx*2+1,l,r,cur,val);
}

int main() {
	//freopen("in.txt","r",stdin);
	scanf("%d%d",&n,&k);
	for(int i=0;i<n;i++){
		int a, b, c;
		scanf("%d%d%d",&a,&b,&c);
		f[c].push_back(make_pair(a,b));
	}
	for(int i=0;i<N;i++){
		if(f[i].size() == 0) continue;
		sort(f[i].begin(),f[i].end());
		seg[i].resize(4*f[i].size());
		build(0,f[i].size()-1,1,i);
	}
	long long ans = 0 ;
	for(int i=0;i<N;i++){
		for(int j=0;j<f[i].size();j++){
			for(int l=max(0,i-k);l<=i+k;l++){
				if(f[l].size() == 0) continue;
				int L = lower_bound(f[l].begin(),f[l].end(),make_pair(f[i][j].first-f[i][j].second,0)) - f[l].begin();
				int r = upper_bound(f[l].begin(),f[l].end(),make_pair(f[i][j].first+f[i][j].second,oo)) - f[l].begin() - 1;
				if(r < L) continue;
				if(l > i)
					ans += getsum2(0,f[l].size()-1,1,L,r,l,f[i][j].second);
				else
					ans += getsum(0,f[l].size()-1,1,L,r,l,f[i][j].second);
			}
			if(j > 0)
				ans += getsum3(0,f[i].size()-1,1,0,j-1,i,f[i][j].second);
		}
	}
	cout << ans << endl;
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define oo 2000000000
const int N = 10010;
int n , k;
vector< pair<int,int> > f[N];
vector< vector<int> > seg[N];

void merge(vector<int> &v1,vector<int> &v2,vector<int> &v3){
	int j = 0;
	for(int i=0;i<v2.size();i++){
		while(j < v3.size() && v3[j] < v2[i]) v1.push_back(v3[j++]);
		v1.push_back(v2[i]);
	}
	while(j < v3.size()) v1.push_back(v3[j++]);
}

void build(int s,int e,int idx,int cur){
	if(s == e){
		seg[cur][idx].push_back(f[cur][s].second);
		return ;
	}
	build(s,(s+e)/2,idx*2,cur);
	build((s+e)/2+1,e,idx*2+1,cur);
	merge(seg[cur][idx],seg[cur][idx*2],seg[cur][idx*2+1]);
}

int getsum(int s,int e,int idx,int l,int r,int cur,int val){
	if(s > r || e < l) return 0;
	if(s >= l && e <= r) return seg[cur][idx].end() - upper_bound(seg[cur][idx].begin(),seg[cur][idx].end(),val);
	return getsum(s,(s+e)/2,idx*2,l,r,cur,val) + getsum((s+e)/2+1,e,idx*2+1,l,r,cur,val);
}

int getsum2(int s,int e,int idx,int l,int r,int cur,int val){
	if(s > r || e < l) return 0;
	if(s >= l && e <= r) return seg[cur][idx].end() - lower_bound(seg[cur][idx].begin(),seg[cur][idx].end(),val);
	return getsum2(s,(s+e)/2,idx*2,l,r,cur,val) + getsum2((s+e)/2+1,e,idx*2+1,l,r,cur,val);
}

int getsum3(int s,int e,int idx,int l,int r,int cur,int val){
	if(s > r || e < l) return 0;
	if(s >= l && e <= r) return upper_bound(seg[cur][idx].begin(),seg[cur][idx].end(),val) - lower_bound(seg[cur][idx].begin(),seg[cur][idx].end(),val);
	return getsum2(s,(s+e)/2,idx*2,l,r,cur,val) + getsum2((s+e)/2+1,e,idx*2+1,l,r,cur,val);
}

int main() {
	//freopen("in.txt","r",stdin);
	scanf("%d%d",&n,&k);
	for(int i=0;i<n;i++){
		int a, b, c;
		scanf("%d%d%d",&a,&b,&c);
		f[c].push_back(make_pair(a,b));
	}
	for(int i=0;i<N;i++){
		if(f[i].size() == 0) continue;
		sort(f[i].begin(),f[i].end());
		seg[i].resize(4*f[i].size());
		build(0,f[i].size()-1,1,i);
	}
	long long ans = 0 ;
	for(int i=0;i<N;i++){
		for(int j=0;j<f[i].size();j++){
			for(int l=max(1,i-k);l<=i+k;l++){
				if(i == l) continue;
				if(f[l].size() == 0) continue;
				int L = lower_bound(f[l].begin(),f[l].end(),make_pair(f[i][j].first-f[i][j].second,0)) - f[l].begin();
				int r = upper_bound(f[l].begin(),f[l].end(),make_pair(f[i][j].first+f[i][j].second,oo)) - f[l].begin() - 1;
				if(r < L) continue;
				if(l <= i)
					ans += getsum(0,f[l].size()-1,1,L,r,l,f[i][j].second);
				else
					ans += getsum2(0,f[l].size()-1,1,L,r,l,f[i][j].second);
			}
			if(j > 0){
				int idx = lower_bound(f[i].begin(),f[i].end(),make_pair(f[i][j].first-f[i][j].second,0)) - f[i].begin();
				if(idx < j)
					ans += getsum3(0,f[i].size()-1,1,idx,j-1,i,f[i][j].second);
			}
		}
	}
	cout << ans << endl;
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
#define mod 1000000007
#define oo 2000000000
const int N = 10010;
int n , k;
vector< pair<int,int> > f[N];
vector< vector<int> > seg[N];

void merge(vector<int> &v1,vector<int> &v2,vector<int> &v3){
	int j = 0;
	for(int i=0;i<v2.size();i++){
		while(j < v3.size() && v3[j] < v2[i]) v1.push_back(v3[j++]);
		v1.push_back(v2[i]);
	}
	while(j < v3.size()) v1.push_back(v3[j++]);
}

void build(int s,int e,int idx,int cur){
	if(s == e){
		seg[cur][idx].push_back(f[cur][s].second);
		return ;
	}
	build(s,(s+e)/2,idx*2,cur);
	build((s+e)/2+1,e,idx*2+1,cur);
	merge(seg[cur][idx],seg[cur][idx*2],seg[cur][idx*2+1]);
}

int getsum(int s,int e,int idx,int l,int r,int cur,int val){
	if(s > r || e < l) return 0;
	if(s >= l && e <= r) return seg[cur][idx].end() - upper_bound(seg[cur][idx].begin(),seg[cur][idx].end(),val);
	return getsum(s,(s+e)/2,idx*2,l,r,cur,val) + getsum((s+e)/2+1,e,idx*2+1,l,r,cur,val);
}

int getsum2(int s,int e,int idx,int l,int r,int cur,int val){
	if(s > r || e < l) return 0;
	if(s >= l && e <= r) return seg[cur][idx].end() - lower_bound(seg[cur][idx].begin(),seg[cur][idx].end(),val);
	return getsum2(s,(s+e)/2,idx*2,l,r,cur,val) + getsum2((s+e)/2+1,e,idx*2+1,l,r,cur,val);
}

int main() {
	//freopen("in.txt","r",stdin);
	scanf("%d%d",&n,&k);
	for(int i=0;i<n;i++){
		int a, b, c;
		scanf("%d%d%d",&a,&b,&c);
		f[c].push_back(make_pair(a,b));
	}
	for(int i=0;i<N;i++){
		if(f[i].size() == 0) continue;
		sort(f[i].begin(),f[i].end());
		seg[i].resize(4*f[i].size());
		build(0,f[i].size()-1,1,i);
	}
	long long ans = 0 ;
	for(int i=0;i<N;i++){
		for(int j=0;j<f[i].size();j++){
			for(int l=max(1,i-k);l<=i+k;l++){
				if(i == l) continue;
				if(f[l].size() == 0) continue;
				int L = lower_bound(f[l].begin(),f[l].end(),make_pair(f[i][j].first-f[i][j].second,0)) - f[l].begin();
				int r = upper_bound(f[l].begin(),f[l].end(),make_pair(f[i][j].first+f[i][j].second,oo)) - f[l].begin() - 1;
				if(r < L) continue;
				if(l > i)
					ans += getsum(0,f[l].size()-1,1,L,r,l,f[i][j].second);
				else
					ans += getsum2(0,f[l].size()-1,1,L,r,l,f[i][j].second);
			}
			if(j > 0){
				int idx = lower_bound(f[i].begin(),f[i].end(),make_pair(f[i][j].first-f[i][j].second,0)) - f[i].begin();
				if(idx < j)
					ans += getsum2(0,f[i].size()-1,1,idx,j-1,i,f[i][j].second);
				int idx2 = upper_bound(f[i].begin(),f[i].end(),make_pair(f[i][j].first+f[i][j].second,oo)) - f[i].begin() - 1;
				if(j <= idx2)
					ans += getsum(0,f[i].size()-1,1,j,idx2,i,f[i][j].second);
			}
		}
	}
	cout << ans << endl;
	return 0;
}