#include <bits/stdc++.h>
using namespace std;
#define tag "spoj"
#define maxn 1007
#define oo 1000000007
#define mid ((l+r)>>1)
#define meset(a,x) memset(a,x,sizeof(a))
#define loop(x) for(int LoOpEr=1;LoOpEr<=x;LoOpEr++)
///>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>
class it2D{
 
    struct item{
 
        int id;
        int l,r;
 
        item(const int &i,const int &L,const int &R): id(i), l(L), r(R) {};
 
        item left()
        const{
            return item(id<<1,l,mid);
        }
 
        item right()
        const{
            return item(id<<1|1,mid+1,r);
        }
 
        bool belong(const int &L,const int &R)
        const{
            return L<=l && r<=R;
        }
        bool irrelevent(const int &L,const int &R)
        const{
            return R<l || L>r;
        }
    };
 
    int m,n;
 
    item rtx,rty;
 
    vector<vector<int>> node;
 
    void update(const item &dx,const item &dy,const int &x,const int &y,const int &val,const bool &only_y)
    {
        if(dx.irrelevent(x,x) || dy.irrelevent(y,y)) return;
 
        if(dx.l==dx.r && dy.l==dy.r) return node[dx.id][dy.id]=val,void();
 
        if(dx.l!=dx.r)
        {
            if(!only_y)
                update(dx.left(),dy,x,y,val,false),
                update(dx.right(),dy,x,y,val,false);
 
            node[dx.id][dy.id]=max(node[dx.left().id][dy.id],node[dx.right().id][dy.id]);
        }
 
        if(dy.l!=dy.r)
        {
            update(dx,dy.left(),x,y,val,true);
            update(dx,dy.right(),x,y,val,true);
 
            if(dx.l==dx.r)
                node[dx.id][dy.id]=max(node[dx.id][dy.left().id],node[dx.id][dy.right().id]);
        }
    }
 
    int get(const item &dx,const item &dy,const int &x1,const int &y1,const int &x2,const int &y2)
    {
        if(dx.irrelevent(x1,x2) || dy.irrelevent(y1,y2)) return 0;
 
        if(dx.belong(x1,x2))
            return  dy.belong(y1,y2) ? node[dx.id][dy.id] : max(get(dx,dy.left(),x1,y1,x2,y2),get(dx,dy.right(),x1,y1,x2,y2));
 
        return max(get(dx.left(),dy,x1,y1,x2,y2),get(dx.right(),dy,x1,y1,x2,y2));
    }
 
public:
 
    it2D(const int &M,const int &N): m(M), n(N), rtx(1,1,M), rty(1,1,N), node(vector<vector<int>>(4*M+7,vector<int>(4*N+7))) {};
 
    void update(const int &x,const int &y,const int &val)
    {
        update(rtx,rty,x,y,val,false);
    }
 
    int max_range(const int &x1,const int &y1,const int &x2,const int &y2)
    {
        return get(rtx,rty,x1,y1,x2,y2);
    }
};
int main()
{
    #ifdef dmdd
    freopen(tag".inp","r",stdin); freopen(tag".out","w",stdout);
    #endif // dmdd
    ios_base::sync_with_stdio(0); cin.tie(0); cout.tie(0);
 
 
    int n,k;
    cin>>n>>k;
    vector<int> x(n+1),y(n+1),z(n+1);
 
    for(int i=1;i<=n;i++) cin>>x[i]>>y[i]>>z[i];
 
    it2D st(2*maxn,2*maxn);
 
    #define krange(x,y) x+y-k,x-y-k+maxn,x+y+k,x-y+k+maxn
    for(int i=n,cur;i>=1;i--)
    {
        cur=st.max_range(krange(x[i],y[i])) + z[i];
 
        st.update(x[i]+y[i],x[i]-y[i]+maxn,cur);
    }
 
    cout<<st.max_range(krange(0,0));
 
    return 0;
}