#include <stdio.h>
#include <assert.h>
#include <fstream>
#include <iostream>
#include <algorithm>
#include <array>
#include <vector>
#include <queue>
#include <set>
#include <cmath>
//#include <unordered_map>
//#include <unordered_set>
//#include <boost/container/static_vector.hpp>
//#include <boost/unordered_set.hpp>
//#include <boost/unordered_map.hpp>
//#include <unistd.h>

//#include <cv.h>
//#include <highgui.h>
#include <stdlib.h>
#include <string>

// binary search result
struct BSR {
    bool found; // 条件を満たす範囲が見つかったか。falseの場合、begin,endは意味を持たない。
    long long begin; // [begin, end]で条件が成り立つ。
    long long end;

    BSR(bool found_in, long long begin_in, long long end_in) : found(found_in), begin(begin_in), end(end_in) {}
};

template<class Fn> BSR my_binary_search(long long L, long long R, Fn func) {
    if (func(L) && func(R)) {
        return BSR(true, L, R);
    } else if (!func(L) && !func(R)) {
        return BSR(false, 0, 0);
    } else {
        long long lb = L;
        long long ub = R;
        while (lb + 1 < ub) {
            long long mid = (lb + ub) / 2;
            if (func(L) == func(mid)) {
                lb = mid;
            } else {
                ub = mid;
            }
        }
        if (func(L)) {
            return BSR(true, L, lb);
        } else {
            return BSR(true, ub, R);
        }
    } 
}

const int MAX_N = 100050;
int N;
long long X;
long long b[MAX_N], l[MAX_N], u[MAX_N];

std::vector<int> pri_max, pri_l, pri_tr;
bool get_max[MAX_N];

bool can_win(long long T) {
    long long rest = 0;
    for (int i = 1; i <= N; i++) {
        rest += l[i] * b[i];
        get_max[i] = false;
    }
    int p = T / X;

    if (X <= T) {
        //for (int i : pri_max) {
        for (int i : pri_tr) {
            rest -= l[i] * b[i];
            rest -= u[i] * (X - b[i]);
            if (rest <= 0) {
                return true;
            }
            T -= X;
            get_max[i] = true;
            if (T < X) {
                break;
            }
        }
    }

    assert(p < pri_tr.size());
    p = pri_tr[p];

    long long tmp1 = l[p] * b[p] + u[p] * (X - b[p]);

    for (int i = 1; i <= N; i++) {
        if (!get_max[i]) {
            if (rest <= l[i] * T) {
                return true;
            }
            if (b[i] < T) {
                if (rest <= l[i] * b[i] + u[i] * (T - b[i])) {
                    return true;
                }
            }
        } else {
            long long tmp2 = l[i] * b[i] + u[i] * (X - b[i]);
            long long tmp3 = b[i] < T ? l[i] * b[i] + u[i] * (T - b[i]) : l[i] * T;
            if (rest + tmp2 <= tmp1 + tmp3) {
                return true;
            }
        }
    }

    return false;
}

int main(int argc, char **argv) {
    std::cin >> N >> X;

    for (int i = 1; i <= N; i++) {
        std::cin >> b[i] >> l[i] >> u[i];
    }

    for (int i = 1; i <= N; i++) {
        pri_max.push_back(i);
        pri_l.push_back(i);
        pri_tr.push_back(i);
    }
    std::sort(pri_max.begin(), pri_max.end(),
        [&](const int i, const int j) { return u[i] * (X - b[i]) > u[j] * (X - b[j]); }
    );

    std::sort(pri_l.begin(), pri_l.end(),
        [&](const int i, const int j) { return l[i] > l[j]; }
    );

    std::sort(pri_tr.begin(), pri_tr.end(),
        [&](const int i, const int j) {
            return l[i] * b[i] + u[i] * (X - b[i]) > l[j] * b[j] + u[j] * (X - b[j]);
        }
    );

    //std::cout << can_win(108) << std::endl;

    BSR bsr = my_binary_search(0, X * N,
        [&](const long long j) { return can_win(j); }
    );

    assert(bsr.found);
    std::cout << bsr.begin << std::endl;

    return 0;
}



Measured memory_bytes: 4076