b939a49c8339c33a0f9a86c89589b239e1f4c59358a98c5cb4c2a4eb0d0b5c9f
// 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;
}