The clique problem is one of the most well-known NP-complete problems. Under some simplification it can be formulated as follows. Consider an undirected graph G. It is required to find a subset of vertices C of the maximum size such that any two of them are connected by an edge in graph G. Sounds simple, doesn't it? Nobody yet knows an algorithm that finds a solution to this problem in polynomial time of the size of the graph. However, as with many other NP-complete problems, the clique problem is easier if you consider a specific type of a graph.

Consider n distinct points on a line. Let the i-th point have the coordinate xi and weight wi. Let's form graph G, whose vertices are these points and edges connect exactly the pairs of points (i, j), such that the distance between them is not less than the sum of their weights, or more formally: |xi - xj| ≥ wi + wj.

Find the size of the maximum clique in such graph.

Input

The first line contains the integer n (1 ≤ n ≤ 200 000) — the number of points.

Each of the next n lines contains two numbers xi, wi (0 ≤ xi ≤ 109, 1 ≤ wi ≤ 109) — the coordinate and the weight of a point. All xi are different.

Output

Print a single number — the number of vertexes in the maximum clique of the given graph.

Examples

Input

4
2 3
3 1
6 1
0 2


Output

3

Note

If you happen to know how to solve this problem without using the specific properties of the graph formulated in the problem statement, then you are able to get a prize of one million dollars!

The picture for the sample test.

<image>
import java.util.*;
import java.io.*;
import java.awt.Point;
import java.math.BigDecimal;
import java.math.BigInteger;

import static java.lang.Math.*;

// Solution is at the bottom of code

public class B implements Runnable{
	
	final boolean ONLINE_JUDGE = System.getProperty("ONLINE_JUDGE") != null;
	
	BufferedReader in;
	OutputWriter out;
	StringTokenizer tok = new StringTokenizer("");
	
	public static void main(String[] args){
		new Thread(null, new B(), "", 128 * (1L << 20)).start();
	}
	
	/////////////////////////////////////////////////////////////////////
	
	void init() throws FileNotFoundException{
		Locale.setDefault(Locale.US);
		
		if (ONLINE_JUDGE){
			in = new BufferedReader(new InputStreamReader(System.in));
			out = new OutputWriter(System.out);
		}else{
			in = new BufferedReader(new FileReader("input.txt"));
			out = new OutputWriter("output.txt");
		}
	}
	
	////////////////////////////////////////////////////////////////
	
	long timeBegin, timeEnd;

	void time(){
		timeEnd = System.currentTimeMillis();
		System.err.println("Time = " + (timeEnd - timeBegin));
	}
	
	void debug(Object... objects){
		if (!ONLINE_JUDGE){
			for (Object o: objects){
				System.err.println(o.toString());
			}
		}
	}
	
	/////////////////////////////////////////////////////////////////////
	
	public void run(){
		try{
			timeBegin = System.currentTimeMillis();
			Locale.setDefault(Locale.US);
			
			init();
			solve();
//			solveSquare();
			
			out.close();
			time();
		}catch (Exception e){
			e.printStackTrace(System.err);
			System.exit(-1);
		}
	}
	
	/////////////////////////////////////////////////////////////////////
	
	String delim = " ";
	
	String readString() throws IOException{
		while(!tok.hasMoreTokens()){
			try{
				tok = new StringTokenizer(in.readLine());
			}catch (Exception e){
				return null;
			}
		}
		
		return tok.nextToken(delim);
	}
	
	String readLine() throws IOException{
		return in.readLine();
	}
	
	/////////////////////////////////////////////////////////////////
	
	final char NOT_A_SYMBOL = '\0';
	
	char readChar() throws IOException{
		int intValue = in.read();
		
		if (intValue == -1){
			return NOT_A_SYMBOL;
		}
		
		return (char) intValue;
	}
	
	char[] readCharArray() throws IOException{
		return readLine().toCharArray();
	}
	
	/////////////////////////////////////////////////////////////////
	
	int readInt() throws IOException {
		return Integer.parseInt(readString());
	}
	
	int[] readIntArray(int size) throws IOException {
		int[] array = new int[size];
		
		for (int index = 0; index < size; ++index){
			array[index] = readInt();
		}
		
		return array;
	}
	
	int[] readSortedIntArray(int size) throws IOException {
		Integer[] array = new Integer[size];
		
		for (int index = 0; index < size; ++index) {
			array[index] = readInt();
		}
		Arrays.sort(array);
		
		int[] sortedArray = new int[size];
		for (int index = 0; index < size; ++index) {
			sortedArray[index] = array[index];
		}
		
		return sortedArray;
	}
	
	int[] readIntArrayWithDecrease(int size) throws IOException {
		int[] array = readIntArray(size);
		
		for (int i = 0; i < size; ++i) {
			array[i]--;
		}
		
		return array;
	}
	
	///////////////////////////////////////////////////////////////////
	
	int[][] readIntMatrix(int rowsCount, int columnsCount) throws IOException {
		int[][] matrix = new int[rowsCount][];
		
		for (int rowIndex = 0; rowIndex < rowsCount; ++rowIndex) {
			matrix[rowIndex] = readIntArray(columnsCount);
		}
		
		return matrix;
	}
	
	int[][] readIntMatrixWithDecrease(int rowsCount, int columnsCount) throws IOException {
		int[][] matrix = new int[rowsCount][];
		
		for (int rowIndex = 0; rowIndex < rowsCount; ++rowIndex) {
			matrix[rowIndex] = readIntArrayWithDecrease(columnsCount);
		}
		
		return matrix;
	}
	
	///////////////////////////////////////////////////////////////////
	
	long readLong() throws IOException{
		return Long.parseLong(readString());
	}
	
	long[] readLongArray(int size) throws IOException{
		long[] array = new long[size];
		
		for (int index = 0; index < size; ++index){
			array[index] = readLong();
		}
		
		return array;
	}
	
	////////////////////////////////////////////////////////////////////
	
	double readDouble() throws IOException{
		return Double.parseDouble(readString());
	}
	
	double[] readDoubleArray(int size) throws IOException{
		double[] array = new double[size];
		
		for (int index = 0; index < size; ++index){
			array[index] = readDouble();
		}
		
		return array;
	}
	
	////////////////////////////////////////////////////////////////////
		
	BigInteger readBigInteger() throws IOException {
		return new BigInteger(readString());
	}
	
	BigDecimal readBigDecimal() throws IOException {
		return new BigDecimal(readString());
	}
	
	/////////////////////////////////////////////////////////////////////
	
	Point readPoint() throws IOException{
		int x = readInt();
		int y = readInt();
		return new Point(x, y);
	}
	
	Point[] readPointArray(int size) throws IOException{
		Point[] array = new Point[size];
		
		for (int index = 0; index < size; ++index){
			array[index] = readPoint();
		}
		
		return array;
	}
	
	/////////////////////////////////////////////////////////////////////
	
	List<Integer>[] readGraph(int vertexNumber, int edgeNumber)
	throws IOException{
		@SuppressWarnings("unchecked")
		List<Integer>[] graph = new List[vertexNumber];
		
		for (int index = 0; index < vertexNumber; ++index){
			graph[index] = new ArrayList<Integer>();
		}
		
		while (edgeNumber-- > 0){
			int from = readInt() - 1;
			int to = readInt() - 1;
			
			graph[from].add(to);
			graph[to].add(from);
		}
		
		return graph;
	}
	
	/////////////////////////////////////////////////////////////////////
	
	static class IntIndexPair {
		
		static Comparator<IntIndexPair> increaseComparator = new Comparator<B.IntIndexPair>() {
			
			@Override
			public int compare(IntIndexPair indexPair1, IntIndexPair indexPair2) {
				int value1 = indexPair1.value;
				int value2 = indexPair2.value;
				
				if (value1 != value2) return value1 - value2;
				
				int index1 = indexPair1.index;
				int index2 = indexPair2.index;
				
				return index1 - index2;
			}
		};
		
		static Comparator<IntIndexPair> decreaseComparator = new Comparator<B.IntIndexPair>() {
			
			@Override
			public int compare(IntIndexPair indexPair1, IntIndexPair indexPair2) {
				int value1 = indexPair1.value;
				int value2 = indexPair2.value;
				
				if (value1 != value2) return -(value1 - value2);
				
				int index1 = indexPair1.index;
				int index2 = indexPair2.index;
				
				return index1 - index2;
			}
		};
		
		int value, index;

		public IntIndexPair(int value, int index) {
			super();
			this.value = value;
			this.index = index;
		}		
		
		public int getRealIndex() {
			return index + 1;
		}
	}
	
	IntIndexPair[] readIntIndexArray(int size) throws IOException {
		IntIndexPair[] array = new IntIndexPair[size];
		
		for (int index = 0; index < size; ++index) {
			array[index] = new IntIndexPair(readInt(), index);
		}
		
		return array;
	}
	
	/////////////////////////////////////////////////////////////////////
	
	static class OutputWriter extends PrintWriter {

		final int DEFAULT_PRECISION = 12;
		
		protected int precision;
		protected String format, formatWithSpace;
		
		{
			precision = DEFAULT_PRECISION;
			
			format = createFormat(precision);
			formatWithSpace = format + " ";
		}
		
		public OutputWriter(OutputStream out) {
			super(out);
		}

		public OutputWriter(String fileName) throws FileNotFoundException {
			super(fileName);
		}
		
		public int getPrecision() {
			return precision;
		}

		public void setPrecision(int precision) {
			precision = max(0, precision);
			this.precision = precision;
			
			format = createFormat(precision);
			formatWithSpace = format + " ";
		}
		
		private String createFormat(int precision){
			return "%." + precision + "f";
		}
		
		@Override
		public void print(double d){
			printf(format, d);
		}
		
		public void printWithSpace(double d){
			printf(formatWithSpace, d);
		}

		public void printAll(double...d){
			for (int i = 0; i < d.length - 1; ++i){
				printWithSpace(d[i]);
			}
			
			print(d[d.length - 1]);
		}
		
		@Override
		public void println(double d){
			printlnAll(d);
		}
		
		public void printlnAll(double... d){
			printAll(d);
			println();
		}
	}
	
	/////////////////////////////////////////////////////////////////////
	
	static final int[][] steps = {{-1, 0}, {1, 0}, {0, -1}, {0, 1}}; 
	static final int[][] steps8 = {
			{-1, 0}, {1, 0}, {0, -1}, {0, 1},
			{-1, -1}, {1, 1}, {1, -1}, {-1, 1}
	};
	
	static final boolean check(int index, int lim){
		return (0 <= index && index < lim);
	}
	
	/////////////////////////////////////////////////////////////////////
	
	static final boolean checkBit(int mask, int bit){
		return (mask & (1 << bit)) != 0;
	}
	
	/////////////////////////////////////////////////////////////////////
	
	static final long getSum(int[] array) {
		long sum = 0;
		for (int value: array) {
			sum += value;
		}
		
		return sum;
	}
	
	static final Point getMinMax(int[] array) {
		int min = array[0];
		int max = array[0];
		
		for (int index = 0, size = array.length; index < size; ++index, ++index) {
			int value = array[index];
			
			if (index == size - 1) {
				min = min(min, value);
				max = max(max, value);
			} else {
				int otherValue = array[index + 1];
				
				if (value <= otherValue) {
					min = min(min, value);
					max = max(max, otherValue);
				} else {
					min = min(min, otherValue);
					max = max(max, value);
				}
			}
		}
		
		return new Point(min, max);
	}
	
	/////////////////////////////////////////////////////////////////////
	
	class MaxSegmentTree {
		
		int size;
		int[] tree;
		
		MaxSegmentTree(int size) {
			this.size = size;
			this.tree = new int[size << 2];
		}
		
		int getPrefMax(int index) {
			return get(1, 0, size - 1, 0, index);
		}
		
		int getSuffMax(int index) {
			return get(1, 0, size - 1, index, size - 1);
		}
		
		int get(int v, int l, int r, int left, int right) {
			if (right < l || r < left) return 0;
			
			if (l == left && r == right) {
				return tree[v];
			} else {
				int vLeft = (v << 1);
				int vRight = (vLeft + 1);
				
				int m = ((l + r) >> 1);
				
				int leftResult = get(vLeft, l, m, left, min(m, right));
				int rightResult = get(vRight, m + 1, r, max(left, m + 1), right);
				
				return max(leftResult, rightResult);
			}
		}
		
		void set(int index, int value) {
			set(1, 0, size - 1, index, value);
		}
		
		int set(int v, int l, int r, int index, int value) {
			if (l == r) {
				return tree[v] = value;
			} else {
				int vLeft = (v << 1);
				int vRight = (vLeft + 1);
				
				int m = ((l + r) >> 1);
				
				if (index <= m) {
					set(vLeft, l, m, index, value);
				} else {
					set(vRight, m + 1, r, index, value);
				}
				
				return tree[v] = max(tree[vLeft], tree[vRight]);
			}
		}
	}
	
	void solve() throws IOException {
		int n = readInt();
		
		int[] x = new int[n];
		int[] w = new int[n];
		
		for (int i = 0; i < n; ++i) {
			x[i] = readInt();
			w[i] = readInt();
		}
		
		IntIndexPair[] decPairs = new IntIndexPair[n];
		IntIndexPair[] incPairs = new IntIndexPair[n];
		
		for (int i = 0; i < n; ++i) {
			decPairs[i] = new IntIndexPair(x[i] - w[i], i);
			incPairs[i] = new IntIndexPair(x[i] + w[i], i);
		}
		
		Arrays.sort(decPairs, IntIndexPair.increaseComparator);
		Arrays.sort(incPairs, IntIndexPair.increaseComparator);
		
		int[] decIndexes = new int[n];
		int[] incIndexes = new int[n];
		
		for (int i = 0; i < n; ++i) {
			decIndexes[decPairs[i].index] = i;
			incIndexes[incPairs[i].index] = i;
		}
		
		TreeMap<Integer, Integer> decMap = new TreeMap<Integer, Integer>();
		TreeMap<Integer, Integer> incMap = new TreeMap<Integer, Integer>();
		
		for (int i = 0; i < n; ++i) {
			decMap.put(decPairs[i].value, i);
			incMap.put(incPairs[i].value, i);
		}
		
		MaxSegmentTree prefTree = new MaxSegmentTree(n);
		int[] prefDp = new int[n];
		
		class Vertex implements Comparable<Vertex> {
			int x, w, index;
			
			Vertex(int x, int w, int index) {
				this.x = x;
				this.w = w;
				this.index = index;
			}
			
			@Override
			public int compareTo(Vertex other) {
				return this.x - other.x;
			}

			@Override
			public String toString() {
				return "Vertex [x=" + x + ", w=" + w + "]";
			}
			
			
		}
		
		Vertex[] v = new Vertex[n];
		for (int i = 0; i < n; ++i) {
			v[i] = new Vertex(x[i], w[i], i);
		}
		
		Arrays.sort(v);
		
		for (int i = 0; i < n; ++i) {
			int curDec = v[i].x - v[i].w;
			
			Integer lastNotGreaterInc = incMap.floorKey(curDec);
			int lastNotGreaterIncIndex = (lastNotGreaterInc == null ? -1 : incMap.get(lastNotGreaterInc));
			
			if (lastNotGreaterIncIndex >= 0) {
				prefDp[i] = prefTree.getPrefMax(lastNotGreaterIncIndex) + 1;
			} else {
				prefDp[i] = 1;
			}
			
			prefTree.set(incIndexes[v[i].index], prefDp[i]);
		}
		
		MaxSegmentTree suffTree = new MaxSegmentTree(n);
		int[] suffDp = new int[n];
		
		for (int i = n - 1; i >= 0; --i) {
			int curInc = v[i].x + v[i].w;
			
			Integer lastLowerDec = decMap.lowerKey(curInc);
			int firstNotLowerDecIndex = (lastLowerDec == null ? 0 : decMap.get(lastLowerDec) + 1);
			
			suffDp[i] = suffTree.getSuffMax(firstNotLowerDecIndex) + 1;
			suffTree.set(decIndexes[v[i].index], suffDp[i]);
		}
		
		int answer = 0;
		for (int i = 0; i < n; ++i) {
			answer = max(answer, prefDp[i] + suffDp[i] - 1);
		}
		
		out.println(answer);
	}
	
	void solveSquare() throws IOException {
		int n = readInt();
		
		int[] x = new int[n];
		int[] w = new int[n];
		
		for (int i = 0; i < n; ++i) {
			x[i] = readInt();
			w[i] = readInt();
		}
		
		class Vertex implements Comparable<Vertex> {
			int x, w;
			
			Vertex(int x, int w) {
				this.x = x;
				this.w = w;
			}
			
			@Override
			public int compareTo(Vertex other) {
				return this.x - other.x;
			}
		}
		
		Vertex[] v = new Vertex[n];
		for (int i = 0; i < n; ++i) {
			v[i] = new Vertex(x[i], w[i]);
		}
		
		Arrays.sort(v);
		
		int[] prefDp = new int[n];
		for (int i = 0; i < n; ++i) {
			int maxPrefDp = 0;
			for (int j = 0; j < i; ++j) {
				if (v[i].x - v[j].x >= v[j].w + v[i].w) {
					maxPrefDp = max(maxPrefDp, prefDp[j]);
				}
			}
			
			prefDp[i] = maxPrefDp + 1;
		}
		
		int[] suffDp = new int[n];
		
		for (int i = n - 1; i >= 0; --i) {
			int maxSuffDp = 0;
			for (int j = i + 1; j < n; ++j) {
				if (v[j].x - v[i].x >= v[j].w + v[i].w) {
					maxSuffDp = max(maxSuffDp, suffDp[j]);
				}
			}
			
			suffDp[i] = maxSuffDp + 1;
		}
		
		int answer = 0;
		for (int i = 0; i < n; ++i) {
			answer = max(answer, prefDp[i] + suffDp[i] - 1);
		}
		
		for (int i = 0; i < n; ++i) {
			if (answer == prefDp[i] + suffDp[i] - 1) {
				debug(i);
			}
		}
		
		debug("Answer");
		out.println(answer);
	}
}

