// Arup Guha
// 11/18/2015
// Solution to 2015 SER D1 Problem: Racing Gems
// Note: I got the idea to solve this from Josh Linge, who solved it in contest.

import java.util.*;
import java.io.*;

public class racinggems {

	public static int n;
	public static int r;
	public static long maxX;
	public static long maxY;
	public static gem[] gems;

	public static void main(String[] args) throws Exception {

		// Set up.
		BufferedReader stdin = new BufferedReader(new InputStreamReader(System.in));
		StringTokenizer tok = new StringTokenizer(stdin.readLine());
		n = Integer.parseInt(tok.nextToken());
		r = Integer.parseInt(tok.nextToken());
		maxX = Long.parseLong(tok.nextToken());
		maxY = Long.parseLong(tok.nextToken());
		gems = new gem[n];

		// Read in gems and sort by y-x from largest to least, breaking ties with max x coming first.
		for (int i=0; i<n; i++) {
			tok = new StringTokenizer(stdin.readLine());
			long x = Long.parseLong(tok.nextToken());
			long y = Long.parseLong(tok.nextToken());
			gems[i] = new gem(r*x, y);
		}
		Arrays.sort(gems);

		// Store all unique x+y values for coordinate compression.
		TreeSet<Long> allSums = new TreeSet<Long>();
		for (int i=0; i<n; i++)
			allSums.add(gems[i].x+gems[i].y);
		int setSize = allSums.size();

		// Store backwards lookup table of these.
		HashMap<Long,Integer> map = new HashMap<Long,Integer>();
		for (int i=0; i<setSize; i++)
			map.put(allSums.pollFirst(), i);

		IntTree iTree = new IntTree(0, map.size()-1);
		int res = 1;
		for (int i=0; i<n; i++) {

			// Get best previous result that we can build off of.
			int index = map.get(gems[i].x+gems[i].y);
			int maxPrev = iTree.atOrAbove(index);
			res = Math.max(res, maxPrev+1);

			// Update the interval tree by adding in this gem to build off of in the future.
			int cur = iTree.query(index, index);
			iTree.change(index, index, maxPrev+1-cur);
		}

		// Any item is fair game now...
		System.out.println(res);
	}
}

class gem implements Comparable<gem> {

	public long x;
	public long y;

	public gem(long myx, long myy) {
		x = myx;
		y = myy;
	}

	public int compareTo(gem other) {
		if (x-y < other.x-other.y) return -1;
		if (x-y > other.x-other.y) return 1;
		if (x > other.x) return -1;
		if (x < other.x) return 1;
		return 0;
	}
}

class IntTree {

	// Stores range for this node.
	public int low;
	public int high;

	// Stores aggregate data for this node.
	public int delta;
	public int value;

	// Pointers to children.
	public IntTree left;
	public IntTree right;

	// Creates an interval tree from myLow to myHigh, inclusive.
	public IntTree(int myLow, int myHigh) {

		low = myLow;
		high = myHigh;
		delta = 0;
		value = 0;

		// Lowest level.
		if (low == high) {
			left = null;
			right = null;
		}

		// Must create more nodes.
		else {
			int mid = (low+high)/2;
			left = new IntTree(low, mid);
			right = new IntTree(mid+1, high);
		}
	}

	// Propogates a change down to child nodes.
	public void prop() {

		// Recursive case, push down.
		if (left != null) {
			left.delta += delta;
			right.delta += delta;
			delta = 0;
		}

		// I put this in, seems to make sense.
		else {
			value += delta;
			delta = 0;
		}
	}

	// Pre-condition: delta is 0.
	public void update() {
		if (left != null)
			value = Math.max(left.value+left.delta, right.value+right.delta);
	}

	// Changes the values in the range [start, end] by "adding" extra.
	public void change(int start, int end, int extra) {

		// Out of range.
		if (high < start || end < low) return;

		// Push down delta.
		prop();

		// Whole range must be updated.
		if (start <= low && high <= end) {
			delta += extra;
			update();
			return;
		}

		// Portions of children have to be changed instead.
		left.change(start, end, extra);
		right.change(start, end, extra);
		update();
	}

	public int atOrAbove(int index) {
		return query(index, high);
	}

	public int query(int start, int end) {

		// Out of range.
		if (high < start || end < low) return  0; /*** Can change ***/

		// Whole range must be returned;
		if (start <= low && high <= end) {
			return value + delta;
		}

		// Get answers from both potions.
		prop();
		int leftSide = left.query(start, end);
		int rightSide = right.query(start, end);
		update();
		return Math.max(leftSide, rightSide);
	}
}
