OI XXX - wyp

// https://szkopul.edu.pl/problemset/problem/uYSQBbTHBiOOoTSIPGvYAjoZ/site/?key=statement

#include <bits/stdc++.h>

// #define GARY_DBG
#define GARY_LIB

#define int int64_t

constexpr int sizik = 100 * 1001;

#define ar std::array

typedef std::vector<std::vector<int>> _kra;

struct Frac {
    int num;
    int den;

    Frac(int n = 0, int d = 1) {
        if (d < 0) {
            n = -n;
            d = -d;
        }
        int g = std::gcd(std::abs(n), d);
        if (g > 0) {
            n /= g;
            d /= g;
        }
        num = n;
        den = d;
    }

    bool operator<(const Frac& o) const { return (__int128)num * o.den < (__int128)o.num * den; }
    bool operator>(const Frac& o) const { return o < *this; }
    bool operator<=(const Frac& o) const { return !(*this > o); }
    bool operator>=(const Frac& o) const { return !(*this < o); }
    bool operator==(const Frac& o) const { return (__int128)num * o.den == (__int128)o.num * den; }
    bool operator!=(const Frac& o) const { return !(*this == o); }

    struct Greater {
        bool operator()(const Frac& a, const Frac& b) const { return a > b; }
    };
};

int pref_d[sizik];
ar<int, sizik> x, d, w, m;

namespace dsu {

ar<int, sizik> rep, l, r;
int Find(int v) {
    if (rep[v] == v) return v;
    return rep[v] = Find(rep[v]);
}
void Union(int u, int v) {
    rep[u] = v;
    l[v] = l[u];
}
void init(int n) {
    for (int i = 0; i <= n; i++) {
        rep[i] = i;
        l[i] = i;
        r[i] = i;
    }
}

} // namespace dsu

std::pair<Frac, bool> spr(int u, int v) {
    int Ru = dsu::r[u];
    int Rv = dsu::r[v];
    int Lv = dsu::l[v];

    int delta_X = x[Rv] - x[Ru] - (pref_d[Rv] - pref_d[Lv - 1]);
    int den = w[Ru] * m[Rv] - w[Rv] * m[Ru];

    if (den <= 0) {
        return {Frac(), false};
    }

    int num = delta_X * m[Ru] * m[Rv];

    return {Frac(num, den), true};
}

struct Query {
    Frac time;
    int id;

    bool operator<(const Query& o) const { return time < o.time; }
};

struct Event {
    Frac time;
    int u, v;
    int Lu, Ru, Lv, Rv;

    bool operator<(const Event& o) const { return time > o.time; }
};

void solve() {
    int n, D, W, M;
    std::cin >> n >> D >> W >> M;

    dsu::init(n);

    std::vector<Query> queries;
    std::priority_queue<Event> pq;

    for (int i = 1; i <= n; i++) {
        std::cin >> x[i] >> d[i] >> w[i] >> m[i];
        pref_d[i] = pref_d[i - 1] + d[i];
    }

    for (int i = 1; i < n; i++) {
        int num = (x[i] + D) * M * m[i];
        int den = W * m[i] - w[i] * M;
        Frac T_i(num, den);
        queries.push_back({T_i, i});
    }

    std::sort(queries.begin(), queries.end());

    for (int i = 1; i < n; i++) {
        auto [t, b] = spr(i, i + 1);
        if (b) {
            pq.push({t, i, i + 1, dsu::l[i], dsu::r[i], dsu::l[i + 1], dsu::r[i + 1]});
        }
    }

    int ans = 1;

    for (const auto& q : queries) {
        auto T = q.time;
        auto id = q.id;

        while (!pq.empty() && pq.top().time <= T) {
            auto e = pq.top();
            pq.pop();

            int u = e.u;
            int v = e.v;

            if (dsu::Find(u) != u || dsu::Find(v) != v || dsu::l[u] != e.Lu || dsu::r[u] != e.Ru || dsu::l[v] != e.Lv || dsu::r[v] != e.Rv) {
                continue;
            }

            dsu::Union(u, v);

            if (dsu::l[v] > 1) {
                int p = dsu::Find(dsu::l[v] - 1);
                auto res = spr(p, v);
                if (res.second) {
                    pq.push({res.first, p, v, dsu::l[p], dsu::r[p], dsu::l[v], dsu::r[v]});
                }
            }
            if (dsu::r[v] < n) {
                int nxt = dsu::Find(dsu::r[v] + 1);
                auto res = spr(v, nxt);
                if (res.second) {
                    pq.push({res.first, v, nxt, dsu::l[v], dsu::r[v], dsu::l[nxt], dsu::r[nxt]});
                }
            }
        }

        int root_i = dsu::Find(id);
        int root_ip1 = dsu::Find(id + 1);

        if (root_i == root_ip1) {
            continue;
        }

        int Ru = dsu::r[root_i];
        int Rv = dsu::r[root_ip1];

        int dziura = x[Rv] - x[Ru] - (pref_d[Rv] - pref_d[Ru]);

        __int128 val = (__int128)(dziura - D) * m[Rv] * m[Ru] * T.den + (__int128)(w[Rv] * m[Ru] - w[Ru] * m[Rv]) * T.num;

        if (val >= 0) {
            ans++;
        }
    }

    std::cout << ans << '\n';
}

int32_t main() {
#ifndef GARY_DBG
    std::ios_base::sync_with_stdio(0);
    std::cin.tie(0);
    std::cout.tie(0);
#endif

    int t = 1;
    // std::cin >> t;

    for (; t > 0; t--) {
        solve();
    }

    return 0;
}