Problem:
Score : 200 points

Problem Statement

In a factory, there are N robots placed on a number line.
Robot i is placed at coordinate X_i and can extend its arms of length L_i in both directions, positive and negative.

We want to remove zero or more robots so that the movable ranges of arms of no two remaining robots intersect.
Here, for each i (1 \leq i \leq N), the movable range of arms of Robot i is the part of the number line between the coordinates X_i - L_i and X_i + L_i, excluding the endpoints.

Find the maximum number of robots that we can keep.

Constraints

1 \leq N \leq 100,000

0 \leq X_i \leq 10^9 (1 \leq i \leq N)

1 \leq L_i \leq 10^9 (1 \leq i \leq N)

If i \neq j, X_i \neq X_j.

All values in input are integers.

Input

Input is given from Standard Input in the following format:

N
X_1 L_1
X_2 L_2
\vdots
X_N L_N

Output

Print the maximum number of robots that we can keep.

Sample Input 1

4
2 4
4 3
9 3
100 5

Sample Output 1

3

By removing Robot 2, we can keep the other three robots.

Sample Input 2

2
8 20
1 10

Sample Output 2

1

Sample Input 3

5
10 1
2 1
4 1
6 1
8 1

Sample Output 3

5

Solution in Java8 (OpenJDK 1.8.0) (judge verdict: Wrong Answer)


import java.io.*;
import java.lang.reflect.Array;
import java.util.*;
import java.util.*;

public class Main {

	public static void main(String[] args) throws NumberFormatException, IOException {
		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		Task solver = new Task();
		int i = 0;
//		int t = in.nextInt();
//		for (; i < t; i++)
		solver.solve(i, in, out);

		out.close();

	}

	static class Task {
		static ArrayList<ArrayList<Integer>> adj;
		static ArrayList<Boolean> visited;
		static int hash(ArrayList<Integer> al) {
			int cur=0;
			for(Integer i:al) {
				cur+= (cur*300001)+i;
			}
			return cur+al.size();
		}
		static int merge(int arr[], int temp[], 
				int left, int mid, int right) 
	{ 
		int inv_count = 0; 

		/* i is index for left subarray*/
		int i = left; 
		
		/* i is index for right subarray*/
		int j = mid; 
		
		/* i is index for resultant merged subarray*/
		int k = left; 
		
		while ((i <= mid - 1) && (j <= right)) 
		{ 
			if (arr[i] <= arr[j]) 
				temp[k++] = arr[i++]; 
			else
			{ 
				temp[k++] = arr[j++]; 

				/* this is tricky -- see above / 
				explanation diagram for merge()*/
				inv_count = inv_count + (mid - i); 
			} 
		} 

		/* Copy the remaining elements of left 
		subarray (if there are any) to temp*/
		while (i <= mid - 1) 
			temp[k++] = arr[i++]; 

		/* Copy the remaining elements of right 
		subarray (if there are any) to temp*/
		while (j <= right) 
			temp[k++] = arr[j++]; 

		/*Copy back the merged elements 
		to original array*/
		for (i=left; i <= right; i++) 
			arr[i] = temp[i]; 

		return inv_count; 
	} 

	// An auxiliary recursive function that 
	// sorts the input array and returns 
	// the number of inversions in the array. 
	static int _mergeSort(int arr[], int temp[], 
							int left, int right) 
	{ 
		int mid, inv_count = 0; 
		if (right > left) 
		{ 
			// Divide the array into two parts and 
			// call _mergeSortAndCountInv() for 
			// each of the parts 
			mid = (right + left)/2; 

			/* Inversion count will be sum of 
			inversions in left-part, right-part 
			and number of inversions in merging */
			inv_count = _mergeSort(arr, temp, 
									left, mid); 
									
			inv_count += _mergeSort(arr, temp, 
									mid+1, right); 

			/*Merge the two parts*/
			inv_count += merge(arr, temp, 
							left, mid+1, right); 
		} 

		return inv_count; 
	} 

	// This function sorts the input 
	// array and returns the number 
	// of inversions in the array 
	static double countSwaps(int arr[], int n) 
	{ 
		int temp[] = new int[n]; 
		return _mergeSort(arr, temp, 0, n - 1); 
	} 


		public void solve(int testNumber, InputReader in, PrintWriter out) {
			int n = in.nextInt();
			int a[]=new int[2*n];
			ArrayList<TCS> al=new ArrayList<TCS>();
			for (int i = 0; i < n; i++) {
				int t1=in.nextInt();
				int t2=in.nextInt();
				al.add(new TCS(t1, t2));
			}
			al.sort(null);
//			System.out.println(al);
			for (int i = 0; i < n; i++) {
				a[2*i]=(int)al.get(i).i1-(int)al.get(i).i2;
				a[2*i+1]=(int)al.get(i).i1+(int)al.get(i).i2;
//				System.out.println(a[2*i]);
//				System.out.println(a[2*i+1]);
				
			}
			double x=(countSwaps(a, a.length)/2.0);
			System.out.println((int)(n-x));
		}

		public static void dfs(int v) {
			visited.set(v - 1, true);
			for (Integer i : adj.get(v - 1)) {
				if (!visited.get(i - 1))
					dfs(i - 1);
			}
		}

		static long modInverse(long a, int m) {
			long g = gcd(a, m);
			if (g != 1) {
				System.out.println("Inverse doesn't exist");
				return 0;
			} else {
				// If a and m are relatively prime, then modulo inverse
				// is a^(m-2) mode m
				return power(a, m - 2, m);
			}
		}

		// To compute x^y under modulo m
		static long power(long x, long y, long m) {
			if (y == 0)
				return 1;

			long p = power(x, y / 2, m) % m;
			p = (p * p) % m;

			if (y % 2 == 0)
				return p;
			else
				return (x * p) % m;
		}

		// Function to return gcd of a and b
		static long gcd(long a, long b) {
			if (a == 0)
				return b;
			return gcd(b % a, a);
		}

		static int highestPowerOf2(int n) {
			return (n & (~(n - 1)));
		}

	}
	// template code

	static class InputReader {
		public BufferedReader reader;
		public StringTokenizer tokenizer;

		public InputReader(InputStream stream) {
			reader = new BufferedReader(new InputStreamReader(stream), 32768);
			tokenizer = null;
		}

		public String next() {
			while (tokenizer == null || !tokenizer.hasMoreTokens()) {
				try {
					tokenizer = new StringTokenizer(reader.readLine());
				} catch (IOException e) {
					throw new RuntimeException(e);
				}
			}
			return tokenizer.nextToken();
		}

		public int nextInt() {
			return Integer.parseInt(next());
		}

		public long nextLong() {
			return Long.parseLong(next());
		}

		public double nextDouble() {
			return Double.parseDouble(next());
		}

	}

}

class Point {
	double x, y;

	public Point(double x, double y) {
		this.x = x;
		this.y = y;
	}

	public double d(Point p2) {

		return Math.sqrt(Math.pow(p2.x - this.x, 2) + Math.pow(p2.y - this.y, 2));
	}

	public Point mp(Point p2) {
		return new Point((p2.x + this.x) / 2, (p2.y + this.y) / 2);
	}
}

class TCS implements Comparable<TCS>, Comparator<TCS> {
	long i1, i2;
	int flag;

	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "i1:" + i1 + "  i2:" + i2;
	}

	TCS(long i1, long i2) {
		this.i1 = i1;
		this.i2 = i2;
	}

	@Override
	public int compareTo(TCS o) {
		// TODO Auto-generated method stub
		return compare(this, o);
	}

	@Override
	public int compare(TCS o1, TCS o2) {
		// TODO Auto-generated method stub
		return (int) ((o1.i1 == o2.i1) ? o1.i2 - o2.i2 : o1.i1 - o2.i1);
	}

	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		return super.hashCode();
	}

	@Override
	public boolean equals(Object obj) {
		// TODO Auto-generated method stub
		return super.equals(obj);
	}

}

class Pair implements Comparator<Pair>, Comparable<Pair> {
	int key, value;

	@Override
	public String toString() {
		// TODO Auto-generated method stub
		return "key:" + key + " value: " + value;
	}

	public Pair(int i, int j) {
		key = i;
		value = j;

	}

	@Override
	public int compare(Pair o1, Pair o2) {
		// TODO Auto-generated method stub
		return o1.compareTo(o2);
	}

	@Override
	public int hashCode() {
		// TODO Auto-generated method stub
		return key;
	}

	@Override
	public int compareTo(Pair o) {
		// TODO Auto-generated method stub
		return this.key - o.key;
	}

}