12
-6712 6
2375 73
4643 197
-5660 215
-378 223
2228 307
3305 340
3449 468
-4389 707
-7161 729
-1838 921
-1655 985
730
 5
1 5
6 7
17127 17
17072 42
17042 77
3
 7
-976754 20479
79929143 911181
9598220 82517
-51609349 810257
67416551 266544
-14170975 307690
-15476178 491195
352
 22
-5301 602
-1400 194
-8512 987
-282 962
6484 494
9091 523
-7744 92
6002 461
5053 305
-1339 272
-821 165
9308 785
929 421
8384 883
1266 157
8411 923
-2949 885
7725 687
6859 197
-7630 867
5031 918
5662 410
41

11 12
 2 3
 5 5
 9 9

#include <bits/stdc++.h>
using namespace std;
constexpr size_t kMaxN{100000 + 100};
constexpr long long inf{kMaxN * 2};
int n, v;
struct Event {
  long long p, q;
  Event(long long p = 0, long long q = 0) {
    this->p = p;
    this->q = q;
  }
  void construct(long long x, long long t) {
    p = -x + t * v;
    q = x + t * v;
  }
};
vector<Event> events;
long long resStartFromZero;
long long resStartFromWhatEver;
void compress(vector<long long> &v) {
  set<long long> vals;
  for (auto it : v) vals.insert(it);
  map<long long, long long> m;
  long long cnt = 0;
  for (auto it : vals) m[it] = cnt++;
  for (int i = 0; i < v.size(); ++i) v[i] = m[v[i]];
}
struct Tree {
  int li, ri;
  long long maxx{0};
  long long val{0};
  ~Tree() {
    if (left != nullptr) delete left;
    if (right != nullptr) delete right;
  }
  Tree *left{nullptr}, *right{nullptr};
  Tree(int li, int ri) {
    this->li = li;
    this->ri = ri;
    if (ri - li + 1 > 1) {
      int mi = (li + ri) / 2;
      left = new Tree(li, mi);
      right = new Tree(mi + 1, ri);
    }
  }
  void maintain() {
    maxx = val;
    if (left != nullptr) maxx = max(maxx, left->maxx);
    if (right != nullptr) maxx = max(maxx, right->maxx);
  }
  void update(int i, long long val) {
    if (ri - li + 1 == 1) {
      this->val = max(this->val, val);
      maintain();
      return;
    }
    int mi = (li + ri) / 2;
    if (i <= mi)
      left->update(i, val);
    else
      right->update(i, val);
    maintain();
  }
  long long getMax(int l, int r) {
    if (l > r) return 0;
    if (li == l && ri == r) return maxx;
    int mi = (li + ri) / 2;
    return max(left->getMax(l, min(r, mi)), right->getMax(max(l, mi + 1), r));
  }
};
long long lisExtended(const vector<long long> &v, int index) {
  Tree *root{nullptr};
  long long res = 0;
  long long needToTake = v[index];
  if (index > 0) {
    root = new Tree(0, needToTake);
    long long firstPartRes = 0;
    for (int i = 0; i < index; ++i) {
      if (v[i] > needToTake) continue;
      long long currentRes = 0;
      long long currentNumber = v[i];
      currentRes = root->getMax(0, currentNumber) + 1;
      root->update(currentNumber, currentRes);
      firstPartRes = max(firstPartRes, currentRes);
    }
    res += firstPartRes;
    delete root;
  }
  if (index < v.size() - 1) {
    root = new Tree(needToTake, v.size());
    long long secondPartRes = 0;
    for (int i = index; i < v.size(); ++i) {
      if (v[i] < needToTake) continue;
      long long currentRes = 0;
      long long currentNumber = v[i];
      currentRes = root->getMax(needToTake, currentNumber) + 1;
      root->update(currentNumber, currentRes);
      secondPartRes = max(secondPartRes, currentRes);
    }
    res += secondPartRes;
    delete root;
  }
  return res;
}
long long lis(const vector<long long> &v) {
  Tree *root = new Tree(0, v.size() - 1);
  long long res = 0;
  for (int i = 0; i < v.size(); ++i) {
    long long currentRes = 0;
    long long currentNumber = v[i];
    currentRes = root->getMax(0, currentNumber) + 1;
    res = max(res, currentRes);
    root->update(currentNumber, currentRes);
  }
  delete root;
  return res;
}
int main() {
  ios_base::sync_with_stdio(false);
  cin >> n;
  {
    vector<pair<long long, long long>> initial;
    for (int i = 0; i < n; ++i) {
      long long x, t;
      cin >> x >> t;
      initial.push_back(make_pair(x, t));
    }
    cin >> v;
    while (!initial.empty()) {
      long long x = initial.back().first;
      long long t = initial.back().second;
      events.push_back(Event());
      events.back().construct(x, t);
      initial.pop_back();
    }
  }
  sort(events.begin(), events.end(), [](const Event &lhs, const Event &rhs) {
    if (lhs.p < rhs.p) return true;
    if (lhs.p > rhs.p) return false;
    return lhs.q < rhs.q;
  });
  vector<long long> qs;
  for (const auto &it : events) qs.push_back(it.q);
  compress(qs);
  resStartFromWhatEver = lis(qs);
  events.push_back(Event());
  events.back().construct(0, 0);
  sort(events.begin(), events.end(), [](const Event &lhs, const Event &rhs) {
    if (lhs.p < rhs.p) return true;
    if (lhs.p > rhs.p) return false;
    return lhs.q < rhs.q;
  });
  qs.clear();
  bool wasIndex = false;
  int index;
  for (int i = 0; i < events.size(); ++i) {
    const auto &it = events[i];
    if (it.p == 0 && it.q == 0) {
      if (!wasIndex) {
        wasIndex = true;
        index = i;
      }
    }
    qs.push_back(it.q);
  }
  compress(qs);
  resStartFromZero = lisExtended(qs, index) - 1;
  cout << resStartFromZero << " " << resStartFromWhatEver << endl;
  return 0;
}
