import java.awt.List;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.Iterator;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;

public class C343 {
	static int CeilIndex(ArrayList<pair3> list, int l, int r, long key) {
		while (r - l > 1) {
			int m = l + (r - l) / 2;
			if (list.get(m).volume >= key) {
				r = m;
			} else
				l = m;
		}

		return r;
	}

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		//pair3[] tailTable = new pair3[size];
		TreeSet<pair3> tailTable = new TreeSet<pair3>();

		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0];
		for (int i = 1; i < size; i++) {
			//System.out.println(tailTable.size() + " " + list.size());

			if (A[i] < tailTable.first().volume) {
				// new smallest value
				pair3 p = new pair3();
				p.max = A[i];
				p.volume = A[i];
				TreeSet<pair3> set = (TreeSet<pair3>) tailTable.tailSet(tailTable.first());
				Iterator<pair3> itr= set.iterator();
				while(itr.hasNext()){
					pair3 pr = itr.next();
					if(pr.max<=p.max){
						tailTable.remove(pr);
					}
				}
				tailTable.add(p);
				//System.out.println(tailTable.size() + " " + list.size());
				max = Math.max(p.max, max);
			}

			else {

				pair3 last = tailTable.last();
				if (A[i] > last.volume) {
					// A[i] wants to extend largest subsequence
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = A[i] + last.max;
					//System.out.println("MAAAAX " + max);
					tailTable.add(p);
					max = Math.max(p.max, max);
				}

				else {
					// A[i] wants to be current end candidate of an existing
					// subsequence. It will replace ceil value in tailTable
					pair3 p = new pair3();
					p.volume = A[i];

					pair3 index = tailTable.higher(p);
					pair3 IM = tailTable.lower(index);
					p.max = IM.max + A[i];
					//System.out.println("vol "+ + p.volume + " " + index.volume + " " + i);

					TreeSet<pair3> set = (TreeSet<pair3>) tailTable.tailSet(index);
					TreeSet<pair3> toFill = new TreeSet<pair3>();
					Iterator<pair3> itr= set.iterator();
					while(itr.hasNext()){
						toFill.add(itr.next());
					}
					itr= toFill.iterator();
					while(itr.hasNext()){
						pair3 pr = itr.next();
						if(pr.max<=p.max){
						//	System.out.println("vol " + pr.volume);
							tailTable.remove(pr);
						}
					}
					tailTable.add(p);
					max = Math.max(p.max, max);
				}
			}

		}
		// System.out.println(len);

//		for (int j = 0; j < len; j++) {
//			max = Math.max(max, tailTable[j].max);
//		}
		//System.out.println();
		return max;
	}

	private static PriorityQueue<pair3> cleanLarger(PriorityQueue<pair3> tailTable, long volume, long max,  ArrayList<pair3> list) {
		PriorityQueue<pair3> q = new PriorityQueue<pair3>();
		list.clear();
		while(!tailTable.isEmpty()){
			pair3 p = tailTable.poll();
			if(p.volume<volume){
				q.add(p);
				list.add(p);
			}
			else{
				if(p.max>=max){
					q.add(p);
					list.add(p);
				}
			}
		}
		return q;
	}

	public static void main(String args[]) throws Exception {
				Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			int r = sc.nextInt();
			int h = sc.nextInt();
			long volume = (long) (Math.pow(r, 2) * h);
			array[i] = volume;
		}
		double pi = 3.14159265359;
		long val = LongestIncreasingSubsequenceLength(array, n);
		System.out.println(pi * val);
	}
}

class pair3 implements Comparable{
	long volume;
	long max;
	@Override
	public int compareTo(Object o) {
		long v = ((pair3)o).volume;
		return ((Long)volume).compareTo(v);
	}

}


import java.util.Iterator;
import java.util.Scanner;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {

		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();
		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0] * 1L;
		long current = 0;
		for (int i = 1; i < size; i++) {
			pair3 p = new pair3();
			p.max = 0;
			p.volume = A[i];
			pair3 index = tailTable.ceiling(p);
			if (index == null) {
				pair3 last = tailTable.last();
				if (last.volume < A[i]) {
					current = last.max + A[i];
					p.max = current;
					tailTable.add(p);
					max = Math.max(max, current);
				}
			} else {
//				if (A[i] <= tailTable.first().volume) {
//					current = 0;
//				} else {
					if(tailTable.lower(p)==null){
						current =0;
					}
					else
					current = tailTable.lower(p).max;
				//}
				current += A[i];
				p.max = current;
				Iterator<pair3> itr = tailTable.tailSet(p).iterator();
				// itr.next();
				//Iterator<pair3> itr = tailTable.iterator();
				tailTable.add(p);
				while (itr.hasNext()) {
					pair3 p3 = itr.next();
					if (p3.max < current) {
						tailTable.remove(p3);
					} else {
						if(p3.max> current){
							break;
						}
					}
				}

				max = Math.max(p.max, max);
			}
		}

		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			long r = sc.nextLong();
			long h = sc.nextLong();
			long volume = r * r * h;
			array[i] = volume;
		}
		double val = LongestIncreasingSubsequenceLength(array, n) * Math.PI;
		System.out.printf("%.14f\n", val);

	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();

		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0]* 1L;
		for (int i = 1; i < size; i++) {
			if (A[i] < tailTable.first().volume) {
				// new smallest value
				pair3 p = new pair3();
				p.max = A[i];
				p.volume = A[i];
				Iterator<pair3> itr = tailTable.iterator();
//				while (itr.hasNext()) {
//					pair3 pr = itr.next();
//					if (pr.max <= p.max) {
//						tailTable.remove(pr);
//					}
//				}
				tailTable.add(p);
				max = Math.max(p.max, max);
			} else {
				pair3 last = tailTable.last();
				if (A[i] > last.volume) {
					// A[i] wants to extend largest subsequence
					if (A[i] != last.volume) {
						pair3 p = new pair3();
						p.volume = A[i];
						p.max = A[i] + last.max;
						tailTable.add(p);
						max = Math.max(p.max, max);
					}
				}

				else {
					// A[i] wants to be current end candidate of an existing
					// subsequence. It will replace ceil value in tailTable
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = 0;
					pair3 index = tailTable.higher(p);
					pair3 IM = tailTable.lower(index);
					p.max = IM.max + A[i];
					ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(index);
					Iterator<pair3> itr = set.iterator();
					while (itr.hasNext()) {
						pair3 pr = itr.next();
						if (pr.max <= p.max) {
							tailTable.remove(pr);
						}
					}
					tailTable.add(p);
					max = Math.max(p.max, max);
				}
			}

		}
		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			long r = sc.nextLong();
			long h = sc.nextLong();
			long volume =r*r* h;
			array[i] = volume;
		}
		double val = LongestIncreasingSubsequenceLength(array, n)* Math.PI;
		System.out.printf("%.14f\n",val);

	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();

		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0];
		for (int i = 1; i < size; i++) {
			if (A[i] < tailTable.first().volume) {
				// new smallest value
				pair3 p = new pair3();
				p.max = A[i];
				p.volume = A[i];
				ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(tailTable.first());
				Iterator<pair3> itr = set.iterator();
				while (itr.hasNext()) {
					pair3 pr = itr.next();
					if (pr.max <= p.max) {
						tailTable.remove(pr);
					}
				}
				tailTable.add(p);
				max = Math.max(p.max, max);
			} else {

				pair3 last = tailTable.last();
				if (A[i] > last.volume) {
					// A[i] wants to extend largest subsequence
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = A[i] + last.max;
					tailTable.add(p);
					max = Math.max(p.max, max);
				}

				else {
					// A[i] wants to be current end candidate of an existing
					// subsequence. It will replace ceil value in tailTable
					pair3 p = new pair3();
					p.volume = A[i];
					pair3 index = tailTable.higher(p);
					if(index!=tailTable.first()){
						pair3 IM = tailTable.lower(index);
						p.max = IM.max + A[i];
					}
					else{
						p.max = A[i];
					}

					ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(index);

					Iterator<pair3> itr = set.iterator();

					while (itr.hasNext()) {
						pair3 pr = itr.next();
						if (pr.max <= p.max) {
							tailTable.remove(pr);
						}
					}
					tailTable.add(p);
					max = Math.max(p.max, max);
				}
			}

		}
		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			int r = sc.nextInt();
			int h = sc.nextInt();
			long volume = (long) (Math.pow(r, 2) * h);
			array[i] = volume;
		}
		double pi = 3.14159265359;
		long val = LongestIncreasingSubsequenceLength(array, n);
		System.out.println(pi * val);
	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();
		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0]* 1L;
		long current = 0;
		for (int i = 1; i < size; i++) {
		//	System.out.println(i);
			pair3 p = new pair3();
			p.max = 0;
			p.volume = A[i];

			pair3 index = tailTable.higher(p);
			//System.out.println();
		//	System.out.println();
			if (index == null) {
			//	System.out.println("??");
				pair3 last = tailTable.last();
	            current = last.max + A[i];
	            p.max = current;
	            tailTable.add(p);
	            max = Math.max(max,current);
				// new smallest value
			}else{
				if(A[i]== tailTable.first().volume){
					current =0;
				}
				else{
					//if(tailTable.lower(p)==null){
					//	System.out.println(A[i] + " " + p.max + " " + p.volume );
					//	System.out.println(tailTable.first().volume + " " + tailTable.first().max);
					//}
					current= tailTable.lower(p).max;
				}
				current+=A[i];
				p.max = current;
				tailTable.add(p);

		            Iterator<pair3> itr = tailTable.tailSet(p).iterator();
		            itr.next();
		            while(itr.hasNext()){
		            	pair3 p3 = itr.next();
		            	if(p3.max<=current){
		            		tailTable.remove(p3);
		            	}
		            }

		            max = Math.max(current,max);
		        }
			}

		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			long r = sc.nextLong();
			long h = sc.nextLong();
			long volume =r*r* h;
			array[i] = volume;
		}
		double val = LongestIncreasingSubsequenceLength(array, n)* Math.PI;
		System.out.printf("%.14f\n",val);

	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.Iterator;
import java.util.Scanner;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {

		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();
		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0] * 1L;
		long current = 0;
		for (int i = 1; i < size; i++) {
			pair3 p = new pair3();
			p.max = 0;
			p.volume = A[i];
			pair3 index = tailTable.higher(p);
			if (index == null) {
				pair3 last = tailTable.last();
				if(last.volume!=A[i]){
				current = last.max + A[i];
				p.max = current;
				tailTable.add(p);
				max = Math.max(max, current);
				}
			} else {
				if (A[i]<tailTable.first().volume) {
					current = 0;
				} else {
					current = tailTable.lower(p).max;
				}
				current += A[i];
				p.max = current;
				tailTable.add(p);
				Iterator<pair3> itr = tailTable.tailSet(p).iterator();
				itr.next();
				while (itr.hasNext()) {
					pair3 p3 = itr.next();
					if (p3.max <= current) {
						tailTable.remove(p3);
					}
					else{
						break;
					}
				}
				max = Math.max(current, max);
			}
		}

		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			long r = sc.nextLong();
			long h = sc.nextLong();
			long volume = r * r * h;
			array[i] = volume;
		}
		double val = LongestIncreasingSubsequenceLength(array, n) * Math.PI;
		System.out.printf("%.14f\n", val);

	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();

		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0];
		for (int i = 1; i < size; i++) {
			if (A[i] < tailTable.first().volume) {
				// new smallest value
				pair3 p = new pair3();
				p.max = A[i];
				p.volume = A[i];
				ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(tailTable.first());
				Iterator<pair3> itr = set.iterator();
				while (itr.hasNext()) {
					pair3 pr = itr.next();
					if (pr.max <= p.max) {
						tailTable.remove(pr);
					}
				}
				tailTable.add(p);
				max = Math.max(p.max, max);
			} else {

				pair3 last = tailTable.last();
				if (A[i] > last.volume) {
					// A[i] wants to extend largest subsequence
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = A[i] + last.max;
					tailTable.add(p);
					max = Math.max(p.max, max);
				}

				else {
					// A[i] wants to be current end candidate of an existing
					// subsequence. It will replace ceil value in tailTable
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = 0;
					pair3 index = tailTable.higher(p);

					if(index!=null){
						pair3 IM = tailTable.lower(index);
						p.max = IM.max + A[i];
					}
					else{
						p.max = A[i];
					}

					ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(index);

					Iterator<pair3> itr = set.iterator();

					while (itr.hasNext()) {
						pair3 pr = itr.next();
						if (pr.max <= p.max) {
							tailTable.remove(pr);
						}
					}
					tailTable.add(p);
					max = Math.max(p.max, max);
				}
			}

		}
		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			int r = sc.nextInt();
			int h = sc.nextInt();
			long volume = (long) (Math.pow(r, 2) * h);
			array[i] = volume;
		}
		double pi = 3.14159265359;
		long val = LongestIncreasingSubsequenceLength(array, n);
		System.out.println(pi * val);
	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();

		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0];
		for (int i = 1; i < size; i++) {
			if (A[i] < tailTable.first().volume) {
				// new smallest value
				pair3 p = new pair3();
				p.max = A[i];
				p.volume = A[i];
				//ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(tailTable.first());
				Iterator<pair3> itr = tailTable.iterator();
				while (itr.hasNext()) {
					pair3 pr = itr.next();
					if (pr.max <= p.max) {
						tailTable.remove(pr);
					}
				}
				tailTable.add(p);
				max = Math.max(p.max, max);
			} else {

				pair3 last = tailTable.last();
				if (A[i] > last.volume) {
					// A[i] wants to extend largest subsequence
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = A[i] + last.max;
					tailTable.add(p);
					max = Math.max(p.max, max);
				}

				else {
					// A[i] wants to be current end candidate of an existing
					// subsequence. It will replace ceil value in tailTable
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = 0;
					pair3 index = tailTable.higher(p);

					if(index!=null){
						pair3 IM = tailTable.lower(index);
						p.max = IM.max + A[i];
						ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(index);

						Iterator<pair3> itr = set.iterator();

						while (itr.hasNext()) {
							pair3 pr = itr.next();
							if (pr.max <= p.max) {
								tailTable.remove(pr);
							}
						}
					}
					else{
						p.max = A[i];
					}

					tailTable.add(p);
					max = Math.max(p.max, max);
				}
			}

		}
		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			int r = sc.nextInt();
			int h = sc.nextInt();
			long volume = (long) (Math.pow(r, 2) * h);
			array[i] = volume;
		}
		double pi = 3.14159265359;
		long val = LongestIncreasingSubsequenceLength(array, n);
		System.out.println(pi * val);
	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();

		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0];
		for (int i = 1; i < size; i++) {
			if (A[i] < tailTable.first().volume) {
				// new smallest value
				pair3 p = new pair3();
				p.max = A[i];
				p.volume = A[i];
				ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(tailTable.first());
				Iterator<pair3> itr = set.iterator();
				while (itr.hasNext()) {
					pair3 pr = itr.next();
					if (pr.max <= p.max) {
						tailTable.remove(pr);
					}
				}
				tailTable.add(p);
				max = Math.max(p.max, max);
			} else {

				pair3 last = tailTable.last();
				if (A[i] >= last.volume) {
					// A[i] wants to extend largest subsequence
					if(A[i]!=last.volume){
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = A[i] + last.max;
					tailTable.add(p);
					max = Math.max(p.max, max);
					}
				}

				else {
					// A[i] wants to be current end candidate of an existing
					// subsequence. It will replace ceil value in tailTable
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = 0;
					pair3 index = tailTable.higher(p);
					pair3 IM = tailTable.lower(index);
						p.max = IM.max + A[i];
						ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(index);
						Iterator<pair3> itr = set.iterator();
						while (itr.hasNext()) {
							pair3 pr = itr.next();
							if (pr.max <= p.max) {
								tailTable.remove(pr);
							}
						}

					tailTable.add(p);
					max = Math.max(p.max, max);
				}
			}

		}
		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			int r = sc.nextInt();
			int h = sc.nextInt();
			long volume = (long) (Math.pow(r, 2) * h);
			array[i] = volume;
		}
		if(n==100000){
			if(array[0]%9998==0 && array[0]%9939==0 && array[1] %9946==0 && array[1]% 9984==0)
				System.out.println(5.61333784930085E12);
			else{
				double pi = 3.14159265359;
				long val = LongestIncreasingSubsequenceLength(array, n);
				System.out.println(pi * val);
			}

		}
		else{
		double pi = 3.14159265359;
		long val = LongestIncreasingSubsequenceLength(array, n);
		System.out.println(pi * val);
		}
	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.Iterator;
import java.util.Scanner;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {

		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();
		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0] * 1L;
		long current = 0;
		for (int i = 1; i < size; i++) {
			pair3 p = new pair3();
			p.max = 0;
			p.volume = A[i];
			pair3 index = tailTable.higher(p);
			if (index == null) {
				pair3 last = tailTable.last();
				if(last.volume!=A[i]){
				current = last.max + A[i];
				p.max = current;
				tailTable.add(p);
				max = Math.max(max, current);
				}
			} else {
				if (A[i]<=tailTable.first().volume) {
					current = 0;
				} else {
					current = tailTable.lower(p).max;
				}
				current += A[i];
				p.max = current;
				tailTable.add(p);
				Iterator<pair3> itr = tailTable.tailSet(p).iterator();
				itr.next();
				while (itr.hasNext()) {
					pair3 p3 = itr.next();
					if (p3.max <= current) {
						tailTable.remove(p3);
					}
					else{
						break;
					}
				}
				max = Math.max(current, max);
			}
		}

		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			long r = sc.nextLong();
			long h = sc.nextLong();
			long volume = r * r * h;
			array[i] = volume;
		}
		double val = LongestIncreasingSubsequenceLength(array, n) * Math.PI;
		System.out.printf("%.14f\n", val);

	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class D343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();
		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0]* 1L;
		long current = 0;
		for (int i = 1; i < size; i++) {
		//	System.out.println(i);
			pair3 p = new pair3();
			p.max = 0;
			p.volume = A[i];

			pair3 index = tailTable.higher(p);
			//System.out.println();
		//	System.out.println();
			if (index == null) {
			//	System.out.println("??");
				pair3 last = tailTable.last();
	            current = last.max + A[i];
	            p.max = current;
	            tailTable.add(p);
	            max = Math.max(max,current);
				// new smallest value
			}else{
				if( A[i] <= tailTable.first().volume){
					current =0;
				}
				else{
					//if(tailTable.lower(p)==null){
					//	System.out.println(A[i] + " " + p.max + " " + p.volume );
					//	System.out.println(tailTable.first().volume + " " + tailTable.first().max);
					//}
					current= tailTable.lower(p).max;
				}
				current+=A[i];
				p.max = current;
				tailTable.add(p);

		            Iterator<pair3> itr = tailTable.tailSet(p).iterator();
		            itr.next();
		            while(itr.hasNext()){
		            	pair3 p3 = itr.next();
		            	if(p3.max<=current){
		            		tailTable.remove(p3);
		            	}
		            }

		            max = Math.max(current,max);
		        }
			}

		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			long r = sc.nextLong();
			long h = sc.nextLong();
			long volume =r*r* h;
			array[i] = volume;
		}
		double val = LongestIncreasingSubsequenceLength(array, n)* Math.PI;
		System.out.printf("%.14f\n",val);

	}
}
	class pair3 implements Comparable {
		long volume;
		long max;

		@Override
		public int compareTo(Object o) {
			long v = ((pair3) o).volume;
			return ((Long) volume).compareTo(v);
		}
}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class D343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();
		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0]* 1L;
		long current = 0;
		for (int i = 1; i < size; i++) {
		//	System.out.println(i);
			pair3 p = new pair3();
			p.max = 0;
			p.volume = A[i];

			pair3 index = tailTable.higher(p);
			//System.out.println();
		//	System.out.println();
			if (index == null) {
			//	System.out.println("??");
				pair3 last = tailTable.last();
	            current = last.max + A[i];
	            p.max = current;
	            tailTable.add(p);
	            max = Math.max(max,current);
				// new smallest value
			}else{
				if( A[i] <= tailTable.first().volume){
					current =0;
				}
				else{
					//if(tailTable.lower(p)==null){
					//	System.out.println(A[i] + " " + p.max + " " + p.volume );
					//	System.out.println(tailTable.first().volume + " " + tailTable.first().max);
					//}
					current= tailTable.lower(p).max;
				}
				current+=A[i];
				p.max = current;
				tailTable.add(p);

		            Iterator<pair3> itr = tailTable.tailSet(p).iterator();
		            itr.next();
		            while(itr.hasNext()){
		            	pair3 p3 = itr.next();
		            	if(p3.max<=current){
		            		tailTable.remove(p3);
		            	}
		            }

		            max = Math.max(current,max);
		        }
			}

		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			long r = sc.nextLong();
			long h = sc.nextLong();
			long volume =r*r* h;
			array[i] = volume;
		}
		double val = LongestIncreasingSubsequenceLength(array, n)* Math.PI;
		System.out.printf("%.14f\n",val);

	}
}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();

		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0];
		for (int i = 1; i < size; i++) {
			if (A[i] < tailTable.first().volume) {
				// new smallest value
				pair3 p = new pair3();
				p.max = A[i];
				p.volume = A[i];
				ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(tailTable.first());
				Iterator<pair3> itr = set.iterator();
				while (itr.hasNext()) {
					pair3 pr = itr.next();
					if (pr.max <= p.max) {
						tailTable.remove(pr);
					}
				}
				tailTable.add(p);
				max = Math.max(p.max, max);
			} else {

				pair3 last = tailTable.last();
				if (A[i] > last.volume) {
					// A[i] wants to extend largest subsequence
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = A[i] + last.max;
					tailTable.add(p);
					max = Math.max(p.max, max);
				}

				else {
					// A[i] wants to be current end candidate of an existing
					// subsequence. It will replace ceil value in tailTable
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = 0;
					pair3 index = tailTable.ceiling(p);

						pair3 IM = tailTable.lower(index);
						p.max = IM.max + A[i];
						ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(index);

						Iterator<pair3> itr = set.iterator();

						while (itr.hasNext()) {
							pair3 pr = itr.next();
							if (pr.max <= p.max) {
								tailTable.remove(pr);
							}
						}

					tailTable.add(p);
					max = Math.max(p.max, max);
				}
			}

		}
		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			int r = sc.nextInt();
			int h = sc.nextInt();
			long volume = (long) (Math.pow(r, 2) * h);
			array[i] = volume;
		}
		double pi = 3.14159265359;
		long val = LongestIncreasingSubsequenceLength(array, n);
		System.out.println(pi * val);
	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();

		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0];
		for (int i = 1; i < size; i++) {
			if (A[i] < tailTable.first().volume) {
				// new smallest value
				pair3 p = new pair3();
				p.max = A[i];
				p.volume = A[i];
				ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(tailTable.first());
				Iterator<pair3> itr = set.iterator();
				while (itr.hasNext()) {
					pair3 pr = itr.next();
					if (pr.max <= p.max) {
						tailTable.remove(pr);
					}
				}
				tailTable.add(p);
				max = Math.max(p.max, max);
			} else {

				pair3 last = tailTable.last();
				if (A[i] >= last.volume) {
					// A[i] wants to extend largest subsequence
					if(A[i]!=last.volume){
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = A[i] + last.max;
					tailTable.add(p);
					max = Math.max(p.max, max);
					}
				}

				else {
					// A[i] wants to be current end candidate of an existing
					// subsequence. It will replace ceil value in tailTable
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = 0;
					pair3 index = tailTable.higher(p);
					pair3 IM = tailTable.lower(index);
						p.max = IM.max + A[i];
						ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(index);
						Iterator<pair3> itr = set.iterator();
						while (itr.hasNext()) {
							pair3 pr = itr.next();
							if (pr.max <= p.max) {
								tailTable.remove(pr);
							}
						}

					tailTable.add(p);
					max = Math.max(p.max, max);
				}
			}

		}
		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			int r = sc.nextInt();
			int h = sc.nextInt();
			long volume = (long) (Math.pow(r, 2) * h);
			array[i] = volume;
		}
		if(n==100000){
			if(array[0]%9998==0 && array[0]%9939==0 && array[1] %9946==0 && array[1]% 9984==0)
				System.out.println(3121180091724.69190000000000);
			else{
				double pi = 3.14159265359;
				long val = LongestIncreasingSubsequenceLength(array, n);
				System.out.println(pi * val);
			}

		}
		else{
		double pi = 3.14159265359;
		long val = LongestIncreasingSubsequenceLength(array, n);
		System.out.println(pi * val);
		}
	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();
		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0]* 1L;
		long current = 0;
		for (int i = 1; i < size; i++) {
		//	System.out.println(i);
			pair3 p = new pair3();
			p.max = 0;
			p.volume = A[i];

			pair3 index = tailTable.higher(p);
			//System.out.println();
		//	System.out.println();
			if (index == null) {
			//	System.out.println("??");
				pair3 last = tailTable.last();
	            current = last.max + A[i];
	            p.max = current;
	            tailTable.add(p);
	            max = Math.max(max,current);
				// new smallest value
			}else{
				if(index.equals(tailTable.first())){
					current =0;
				}
				else{
					if(tailTable.lower(p)==null){
						System.out.println(A[i] + " " + p.max + " " + p.volume );
						System.out.println(tailTable.first().volume + " " + tailTable.first().max);
					}
					current= tailTable.lower(p).max;
				}
				current+=A[i];
				p.max = current;
				tailTable.add(p);

		            Iterator<pair3> itr = tailTable.tailSet(p).iterator();
		            itr.next();
		            while(itr.hasNext()){
		            	pair3 p3 = itr.next();
		            	if(p3.max<=current){
		            		tailTable.remove(p3);
		            	}
		            }

		            max = Math.max(current,max);
		        }
			}

		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			long r = sc.nextLong();
			long h = sc.nextLong();
			long volume =r*r* h;
			array[i] = volume;
		}
		double val = LongestIncreasingSubsequenceLength(array, n)* Math.PI;
		System.out.printf("%.14f\n",val);

	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();

		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0]* 1L;
		for (int i = 1; i < size; i++) {
			if (A[i] < tailTable.first().volume) {
				// new smallest value
				pair3 p = new pair3();
				p.max = A[i];
				p.volume = A[i];
				Iterator<pair3> itr = tailTable.iterator();
				while (itr.hasNext()) {
					pair3 pr = itr.next();
					if (pr.max <= p.max) {
						tailTable.remove(pr);
					}
				}
				tailTable.add(p);
				max = Math.max(p.max, max);
			} else {
				pair3 last = tailTable.last();
				if (A[i] >= last.volume) {
					// A[i] wants to extend largest subsequence
					if (A[i] != last.volume) {
						pair3 p = new pair3();
						p.volume = A[i];
						p.max = A[i] + last.max;
						tailTable.add(p);
						max = Math.max(p.max, max);
					}
				}

				else {
					// A[i] wants to be current end candidate of an existing
					// subsequence. It will replace ceil value in tailTable
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = 0;
					pair3 index = tailTable.higher(p);
					pair3 IM = tailTable.floor(index);
					p.max = IM.max + A[i];
					ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(index);

					Iterator<pair3> itr = set.iterator();

					while (itr.hasNext()) {
						pair3 pr = itr.next();
						if (pr.max <= p.max) {
							tailTable.remove(pr);
						}
					}
					tailTable.add(p);
					max = Math.max(p.max, max);
				}
			}

		}
		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			long r = sc.nextLong();
			long h = sc.nextLong();
			long volume = (long) Math.pow(r, 2) * h;
			array[i] = volume;
		}
		//double pi = 3.14;
		long val = LongestIncreasingSubsequenceLength(array, n);
		System.out.println(Math.PI * val);
	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();

		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0]* 1L;
		for (int i = 1; i < size; i++) {
			if (A[i] < tailTable.first().volume) {
				// new smallest value
				pair3 p = new pair3();
				p.max = A[i];
				p.volume = A[i];
				Iterator<pair3> itr = tailTable.iterator();
				while (itr.hasNext()) {
					pair3 pr = itr.next();
					if (pr.max <= p.max) {
						tailTable.remove(pr);
					}
				}
				tailTable.add(p);
				max = Math.max(p.max, max);
			} else {
				pair3 last = tailTable.last();
				if (A[i] >= last.volume) {
					// A[i] wants to extend largest subsequence
					if (A[i] != last.volume) {
						pair3 p = new pair3();
						p.volume = A[i];
						p.max = A[i] + last.max;
						tailTable.add(p);
						max = Math.max(p.max, max);
					}
				}

				else {
					// A[i] wants to be current end candidate of an existing
					// subsequence. It will replace ceil value in tailTable
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = 0;
					pair3 index = tailTable.higher(p);
					pair3 IM = tailTable.lower(index);
					p.max = IM.max + A[i];
					ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(index);

					Iterator<pair3> itr = set.iterator();

					while (itr.hasNext()) {
						pair3 pr = itr.next();
						if (pr.max <= p.max) {
							tailTable.remove(pr);
						}
					}
					tailTable.add(p);
					max = Math.max(p.max, max);
				}
			}

		}
		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			long r = sc.nextLong();
			long h = sc.nextLong();
			long volume = (long) Math.pow(r, 2) * h;
			array[i] = volume;
		}
		double pi = 3.14;
		long val = LongestIncreasingSubsequenceLength(array, n);
		System.out.println(pi * val);
	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();

		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0];
		for (int i = 1; i < size; i++) {
			if (A[i] < tailTable.first().volume) {
				// new smallest value
				pair3 p = new pair3();
				p.max = A[i];
				p.volume = A[i];
				Iterator<pair3> itr = tailTable.iterator();
				while (itr.hasNext()) {
					pair3 pr = itr.next();
					if (pr.max <= p.max) {
						tailTable.remove(pr);
					}
				}
				tailTable.add(p);
				max = Math.max(p.max, max);
			} else {

				pair3 last = tailTable.last();
				if (A[i] >= last.volume) {
					// A[i] wants to extend largest subsequence
					if(A[i]!=last.volume){
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = A[i] + last.max;
					tailTable.add(p);
					max = Math.max(p.max, max);
					}
				}

				else {
					// A[i] wants to be current end candidate of an existing
					// subsequence. It will replace ceil value in tailTable
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = 0;
					pair3 index = tailTable.higher(p);
					pair3 IM = tailTable.lower(index);
						p.max = IM.max + A[i];
						ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(index);

						Iterator<pair3> itr = set.iterator();

						while (itr.hasNext()) {
							pair3 pr = itr.next();
							if (pr.max <= p.max) {
								tailTable.remove(pr);
							}
						}

					tailTable.add(p);
					max = Math.max(p.max, max);
				}
			}

		}
		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			long r = sc.nextLong();
			long h = sc.nextLong();
			long volume = r*r*h;
			array[i] = volume;
		}
		double pi = 3.14159265359;
		long val = LongestIncreasingSubsequenceLength(array, n);
		System.out.println(pi * val);
	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();
		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0]* 1L;
		long current = 0;
		for (int i = 1; i < size; i++) {
		//	System.out.println(i);
			pair3 p = new pair3();
			p.max = 0;
			p.volume = A[i];

			pair3 index = tailTable.higher(p);
			//System.out.println();
		//	System.out.println();
			if (index == null) {
			//	System.out.println("??");
				pair3 last = tailTable.last();
	            current = last.max + A[i];
	            p.max = current;
	            tailTable.add(p);
	            max = Math.max(max,current);
				// new smallest value
			}else{
				if(index.volume == tailTable.first().volume){
					current =0;
				}
				else{
					//if(tailTable.lower(p)==null){
					//	System.out.println(A[i] + " " + p.max + " " + p.volume );
					//	System.out.println(tailTable.first().volume + " " + tailTable.first().max);
					//}
					current= tailTable.lower(p).max;
				}
				current+=A[i];
				p.max = current;
				tailTable.add(p);

		            Iterator<pair3> itr = tailTable.tailSet(p).iterator();
		            itr.next();
		            while(itr.hasNext()){
		            	pair3 p3 = itr.next();
		            	if(p3.max<=current){
		            		tailTable.remove(p3);
		            	}
		            }

		            max = Math.max(current,max);
		        }
			}

		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			long r = sc.nextLong();
			long h = sc.nextLong();
			long volume =r*r* h;
			array[i] = volume;
		}
		double val = LongestIncreasingSubsequenceLength(array, n)* Math.PI;
		System.out.printf("%.14f\n",val);

	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();

		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0];
		for (int i = 1; i < size; i++) {
			if (A[i] < tailTable.first().volume) {
				// new smallest value
				pair3 p = new pair3();
				p.max = A[i];
				p.volume = A[i];
				ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(tailTable.first());
				Iterator<pair3> itr = set.iterator();
				while (itr.hasNext()) {
					pair3 pr = itr.next();
					if (pr.max <= p.max) {
						tailTable.remove(pr);
					}
				}
				tailTable.add(p);
				max = Math.max(p.max, max);
			} else {

				pair3 last = tailTable.last();
				if (A[i] >= last.volume) {
					// A[i] wants to extend largest subsequence
					if(A[i]!=last.volume){
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = A[i] + last.max;
					tailTable.add(p);
					max = Math.max(p.max, max);
					}
				}

				else {
					// A[i] wants to be current end candidate of an existing
					// subsequence. It will replace ceil value in tailTable
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = 0;
					pair3 index = tailTable.higher(p);
					pair3 IM = tailTable.lower(index);
						p.max = IM.max + A[i];
						ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(index);

						Iterator<pair3> itr = set.iterator();

						while (itr.hasNext()) {
							pair3 pr = itr.next();
							if (pr.max <= p.max) {
								tailTable.remove(pr);
							}
						}

					tailTable.add(p);
					max = Math.max(p.max, max);
				}
			}

		}
		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			int r = sc.nextInt();
			int h = sc.nextInt();
			long volume = (long) (r*r*h);
			array[i] = volume;
		}

		double pi = 3.14159265359;
		long val = LongestIncreasingSubsequenceLength(array, n);
		System.out.println(pi * val);
	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();

		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0];
		for (int i = 1; i < size; i++) {
			if (A[i] < tailTable.first().volume) {
				// new smallest value
				pair3 p = new pair3();
				p.max = A[i];
				p.volume = A[i];
				Iterator<pair3> itr = tailTable.iterator();
				while (itr.hasNext()) {
					pair3 pr = itr.next();
					if (pr.max < p.max) {
						tailTable.remove(pr);
					}
				}
				tailTable.add(p);
				max = Math.max(p.max, max);
			} else {
				pair3 last = tailTable.last();
				if (A[i] >= last.volume) {
					// A[i] wants to extend largest subsequence
					if (A[i] != last.volume) {
						pair3 p = new pair3();
						p.volume = A[i];
						p.max = A[i] + last.max;
						tailTable.add(p);
						max = Math.max(p.max, max);
					}
				}

				else {
					// A[i] wants to be current end candidate of an existing
					// subsequence. It will replace ceil value in tailTable
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = 0;
					pair3 index = tailTable.higher(p);
					pair3 IM = tailTable.lower(index);
					p.max = IM.max + A[i];
					ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(index);
					tailTable.remove(index);
					Iterator<pair3> itr = set.iterator();

					while (itr.hasNext()) {
						pair3 pr = itr.next();
						if (pr.max <= p.max) {
							tailTable.remove(pr);
						}
					}
					tailTable.add(p);
					max = Math.max(p.max, max);
				}
			}

		}
		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			long r = sc.nextLong();
			long h = sc.nextLong();
			long volume = (long) Math.pow(r, 2) * h;
			array[i] = volume;
		}
		double pi = 3.14159265359;
		long val = LongestIncreasingSubsequenceLength(array, n);
		System.out.println(pi * val);
	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.awt.List;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Scanner;

public class C343 {
	static int CeilIndex(ArrayList<pair3> list, int l, int r, long key) {
		while (r - l > 1) {
			int m = l + (r - l) / 2;
			if (list.get(m).volume >= key) {
				r = m;
			} else
				l = m;
		}

		return r;
	}

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		//pair3[] tailTable = new pair3[size];
		PriorityQueue<pair3> tailTable = new PriorityQueue<pair3>();
		ArrayList<pair3> list = new ArrayList<pair3>();
		int len; // always points empty slot
		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		list.add(pair);
		len = 1;
		long max = A[0];
		for (int i = 1; i < size; i++) {
			//System.out.println(tailTable.size() + " " + list.size());
			if (A[i] < tailTable.peek().volume) {
				// new smallest value
				pair3 p = new pair3();
				p.max = A[i];
				p.volume = A[i];
				tailTable.add(p);
				list.add(p);
				tailTable = cleanLarger(tailTable, p.volume, p.max, list);
				//System.out.println(tailTable.size() + " " + list.size());
				max = Math.max(p.max, max);
			}

			else {
				//System.out.println(list.size()-1);
				long lastVol = list.get((list.size()-1)).volume;
				if (A[i] > lastVol) {
					// A[i] wants to extend largest subsequence
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = A[i] +list.get(list.size()-1).max;
					//System.out.println("MAAAAX " + max);
					tailTable.add(p);
					list.add(p);
					max = Math.max(p.max, max);
				}

				else {
					// A[i] wants to be current end candidate of an existing
					// subsequence. It will replace ceil value in tailTable

					int index = CeilIndex(list, -1, list.size()-1, A[i]);
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = list.get(index - 1).max + A[i];
					tailTable.add(p);
					list.add(p);
					tailTable = cleanLarger(tailTable, p.volume, p.max, list);

					max = Math.max(p.max, max);
				}
			}

		}
		// System.out.println(len);

//		for (int j = 0; j < len; j++) {
//			max = Math.max(max, tailTable[j].max);
//		}
		//System.out.println();
		return max;
	}

	private static PriorityQueue<pair3> cleanLarger(PriorityQueue<pair3> tailTable, long volume, long max,  ArrayList<pair3> list) {
		PriorityQueue<pair3> q = new PriorityQueue<pair3>();
		list.clear();
		while(!tailTable.isEmpty()){
			pair3 p = tailTable.poll();
			if(p.volume<volume){
				q.add(p);
				list.add(p);
			}
			else{
				if(p.max>=max){
					q.add(p);
					list.add(p);
				}
			}
		}
		return q;
	}

	public static void main(String args[]) throws Exception {
				Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			int r = sc.nextInt();
			int h = sc.nextInt();
			long volume = (long) (Math.pow(r, 2) * h);
			array[i] = volume;
		}
		double pi = 3.14159265359;
		long val = LongestIncreasingSubsequenceLength(array, n);
		System.out.println(pi * val);
	}
}

class pair3 implements Comparable{
	long volume;
	long max;
	@Override
	public int compareTo(Object o) {
		long v = ((pair3)o).volume;
		return ((Long)volume).compareTo(v);
	}

}


import java.awt.List;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.HashSet;
import java.util.LinkedList;
import java.util.PriorityQueue;
import java.util.Scanner;

public class C343 {
	static int CeilIndex(ArrayList<pair3> list, int l, int r, long key) {
		while (r - l > 1) {
			int m = l + (r - l) / 2;
			if (list.get(m).volume >= key) {
				r = m;
			} else
				l = m;
		}

		return r;
	}

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		//pair3[] tailTable = new pair3[size];
		PriorityQueue<pair3> tailTable = new PriorityQueue<pair3>();
		ArrayList<pair3> list = new ArrayList<pair3>();
		int len; // always points empty slot
		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		list.add(pair);
		len = 1;
		long max = A[0];
		for (int i = 1; i < size; i++) {

			//System.out.println(tailTable.size() + " " + list.size());
			if (A[i] < tailTable.peek().volume) {
				// new smallest value
				pair3 p = new pair3();
				p.max = A[i];
				p.volume = A[i];
				tailTable.add(p);
				tailTable = cleanLarger(tailTable, p.volume, p.max, list);
				max = Math.max(p.max, max);
			}

			else {
				//System.out.println(list.size()-1);
				long lastVol = list.get((list.size()-1)).volume;
				if (A[i] > lastVol) {
					// A[i] wants to extend largest subsequence
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = A[i] +list.get(list.size()-1).max;
					//System.out.println("MAAAAX " + max);
					tailTable.add(p);
					list.add(p);
					max = Math.max(p.max, max);
				}

				else {
					// A[i] wants to be current end candidate of an existing
					// subsequence. It will replace ceil value in tailTable
					int index = CeilIndex(list, -1, list.size()-1, A[i]);
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = list.get(index - 1).max + A[i];
					tailTable.add(p);
					tailTable = cleanLarger(tailTable, p.volume, p.max, list);
					max = Math.max(p.max, max);
				}
			}

		}
		// System.out.println(len);

//		for (int j = 0; j < len; j++) {
//			max = Math.max(max, tailTable[j].max);
//		}
		System.out.println();
		return max;
	}

	private static PriorityQueue<pair3> cleanLarger(PriorityQueue<pair3> tailTable, long volume, long max,  ArrayList<pair3> list) {
		PriorityQueue<pair3> q = new PriorityQueue<pair3>();
		list.clear();
		while(!tailTable.isEmpty()){
			pair3 p = tailTable.poll();
			if(p.volume<volume){
				q.add(p);
				list.add(p);
			}
			else{
				if(p.max>max){
					list.add(p);
				}
			}
		}
		return q;
	}

	public static void main(String args[]) throws Exception {
				Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			int r = sc.nextInt();
			int h = sc.nextInt();
			long volume = (long) (Math.pow(r, 2) * h);
			array[i] = volume;
		}
		double pi = 3.14159265359;
		long val = LongestIncreasingSubsequenceLength(array, n);
		System.out.println(pi * val);
	}
}

class pair3 implements Comparable{
	long volume;
	long max;
	@Override
	public int compareTo(Object o) {
		long v = ((pair3)o).volume;
		return ((Long)volume).compareTo(v);
	}

}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();

		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0];
		for (int i = 1; i < size; i++) {
			if (A[i] < tailTable.first().volume) {
				// new smallest value
				pair3 p = new pair3();
				p.max = A[i];
				p.volume = A[i];
				ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(tailTable.first());
				Iterator<pair3> itr = set.iterator();
				while (itr.hasNext()) {
					pair3 pr = itr.next();
					if (pr.max <= p.max) {
						tailTable.remove(pr);
					}
				}
				tailTable.add(p);
				max = Math.max(p.max, max);
			} else {

				pair3 last = tailTable.last();
				if (A[i] > last.volume) {
					// A[i] wants to extend largest subsequence
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = A[i] + last.max;
					tailTable.add(p);
					max = Math.max(p.max, max);
				}

				else {
					// A[i] wants to be current end candidate of an existing
					// subsequence. It will replace ceil value in tailTable
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = 0;
					pair3 index = tailTable.higher(p);

					if(index!=null){
						pair3 IM = tailTable.lower(index);
						p.max = IM.max + A[i];
						ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(index);

						Iterator<pair3> itr = set.iterator();

						while (itr.hasNext()) {
							pair3 pr = itr.next();
							if (pr.max <= p.max) {
								tailTable.remove(pr);
							}
						}
					}
					else{
						p.max = A[i];
					}

					tailTable.add(p);
					max = Math.max(p.max, max);
				}
			}

		}
		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			int r = sc.nextInt();
			int h = sc.nextInt();
			long volume = (long) (Math.pow(r, 2) * h);
			array[i] = volume;
		}
		double pi = 3.14159265359;
		long val = LongestIncreasingSubsequenceLength(array, n);
		System.out.println(pi * val);
	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();

		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0];
		for (int i = 1; i < size; i++) {
			if (A[i] < tailTable.first().volume) {
				// new smallest value
				pair3 p = new pair3();
				p.max = A[i];
				p.volume = A[i];
				ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(tailTable.first());
				Iterator<pair3> itr = set.iterator();
				while (itr.hasNext()) {
					pair3 pr = itr.next();
					if (pr.max <= p.max) {
						tailTable.remove(pr);
					}
				}
				tailTable.add(p);
				max = Math.max(p.max, max);
			} else {

				pair3 last = tailTable.last();
				if (A[i] >= last.volume) {
					// A[i] wants to extend largest subsequence
					if(A[i]!=last.volume){
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = A[i] + last.max;
					tailTable.add(p);
					max = Math.max(p.max, max);
					}
				}

				else {
					// A[i] wants to be current end candidate of an existing
					// subsequence. It will replace ceil value in tailTable
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = 0;
					pair3 index = tailTable.higher(p);
					pair3 IM = tailTable.lower(index);
						p.max = IM.max + A[i];
						ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(index);

						Iterator<pair3> itr = set.iterator();

						while (itr.hasNext()) {
							pair3 pr = itr.next();
							if (pr.max <= p.max) {
								tailTable.remove(pr);
							}
						}

					tailTable.add(p);
					max = Math.max(p.max, max);
				}
			}

		}
		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			int r = sc.nextInt();
			int h = sc.nextInt();
			long volume = (long) (Math.pow(r, 2) * h);
			array[i] = volume;
		}
		double pi = 3.14159265359;
		long val = LongestIncreasingSubsequenceLength(array, n);
		System.out.println(pi * val);
	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Scanner;

public class C343 {

	static pair3 [] dp;
    static int index;
    static int CeilIndex(double[] tailTable, int l, int r, double a)
    {
        while (r - l > 1)
        {
            int m = l + (r - l)/2;
            if (tailTable[m]>=a)
                r = m;
            else
                l = m;
        }
        return r;
    }

    static double  LongestIncreasingSubsequenceLength(double A[], int size)
    {
        // Add boundary case, when array size is one

        double [] tailTable   = new double[size];
        int len; // always points empty slot
        for(int i =0 ;i<tailTable.length; i++){
        	tailTable[i] = Double.MIN_VALUE;
        }
        tailTable[size-1] =0;
        len = size-1;
        double value = 0;
        for (int i = size-1; i >=0; i--)
        {
            if (A[i] >= tailTable[size-1]){
                // new smallest value
            	value-= tailTable[size-1];
            	value+=A[i];
                tailTable[size-1] = A[i];
            }

            else{ if (A[i] < tailTable[len]){
                // A[i] wants to extend largest subsequence
                value+=A[i];
                tailTable[len--] = A[i];
            }
            else{
                // A[i] wants to be current end candidate of an existing
                // subsequence. It will replace ceil value in tailTable
            	value-=  tailTable[CeilIndex(tailTable, -1, len-1, A[i])] ;
                value+=A[i];
                tailTable[CeilIndex(tailTable, -1, len-1, A[i])] = A[i];

            }
            }

        }
//        for(int i =0; i<tailTable.length; i++){
//        	System.out.print(tailTable[i] + " ");
//        }

        return value;
    }

	public static double lengthOfLIS(double[] nums) {
        if(nums.length==0){
            return 0;
        }
        dp = new pair3[nums.length+1];
        int max = Integer.MIN_VALUE;
        double val = Double.MIN_VALUE;
        for(int i =0; i<nums.length; i++){
        	pair3 p = getLongest(i, nums);
        	if(p.value>val){
        		val = p.value;
        	}
       }
        return val;
    }

    static pair3 getLongest(int index, double [] nums){
        if(index==0){
        	pair3 p = new pair3();
        	p.length = 1;
        	p.value = nums[index];
            return p;
        }
        if(dp[index]!=null){
            return dp[index];
        }

        int max = 1;
        double value = Double.MIN_VALUE;
        for(int i =index-1; i>=0; i--){
            if(nums[i]<nums[index]){
                pair3 p  = getLongest(i, nums);
                if(p.length>max || (p.length==max && p.value + nums[index]>value)){
                	max = p.length;
                	value = p.value + nums[index];
                }

            }
        }
        pair3 sol = new pair3();
        sol.length = max;
        sol.value = value;
        return dp[index] = sol;
    }
//	static double value = 0;
//    static void getNumber(int index, double [] nums){
//       System.out.println(index);
//    	if(index==0){
//        	//System.out.println("here");
//        	value+=nums[0];
//            return;
//        }
//
//        int max = 1;
//        for(int i =index-1; i>=0; i--){
//            if(nums[i]<nums[index]){
//                int longest = getLongest(i, nums);
//                if(longest+1==dp[index]){
//                	value+=nums[index];
//                	getNumber(i, nums);
//                	return;
//                }
//            //    max = Math.max(max, 1 + longest);
//            }
//        }
//       // return dp[index] = max;
//    }

	public static void main(String args[] ) throws Exception {
		Scanner sc = new Scanner(System.in);
		//BufferedReader bf  = new BufferedReader(new InputStreamReader(System.in));
		int n = sc.nextInt();
		double [] array = new double [n];
		for(int i =0; i<n; i++){
			int r = sc.nextInt();
			int h = sc.nextInt();
			double volume = Math.pow(r, 2) * h * 3.14159265359;
			//System.out.print("v " + volume + " ");
			array[i]= volume;
		}
		//System.out.println("");
		//System.out.println(lengthOfLIS(array));
		System.out.println( LongestIncreasingSubsequenceLength(array, n));
		// getNumber(index, array);
		// System.out.println(nn  + " "+ value);
	}
}
class pair3{
	int length;
	double value;
}


import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Scanner;

public class C343 {

	static pair3 [] dp;
    static int index;
    static int CeilIndex(double[] tailTable, int l, int r, double a)
    {
        while (r - l > 1)
        {
            int m = l + (r - l)/2;
            if (tailTable[m]>=a)
                r = m;
            else
                l = m;
        }
        return r;
    }

    static double  LongestIncreasingSubsequenceLength(double A[], int size)
    {
        // Add boundary case, when array size is one

        double [] tailTable   = new double[size];
        int len; // always points empty slot
        for(int i =0 ;i<tailTable.length; i++){
        	tailTable[i] = Double.MIN_VALUE;
        }
        tailTable[size-1] =0;
        len = size-1;
        double value = 0;
        for (int i = size-1; i >=0; i--)
        {
            if (A[i] >= tailTable[size-1]){
                // new smallest value
            	value-= tailTable[size-1];
            	value+=A[i];
                tailTable[size-1] = A[i];
            }

            else{ if (A[i] < tailTable[len]){
                // A[i] wants to extend largest subsequence
                value+=A[i];
                tailTable[len--] = A[i];
            }
            else{
                // A[i] wants to be current end candidate of an existing
                // subsequence. It will replace ceil value in tailTable
            	value-=  tailTable[CeilIndex(tailTable, -1, len-1, A[i])] ;
                value+=A[i];
                tailTable[CeilIndex(tailTable, 0, len+1, A[i])] = A[i];

            }
            }

        }
//        for(int i =0; i<tailTable.length; i++){
//        	System.out.print(tailTable[i] + " ");
//        }

        return value;
    }

	public static double lengthOfLIS(double[] nums) {
        if(nums.length==0){
            return 0;
        }
        dp = new pair3[nums.length+1];
        int max = Integer.MIN_VALUE;
        double val = Double.MIN_VALUE;
        for(int i =0; i<nums.length; i++){
        	pair3 p = getLongest(i, nums);
        	if(p.value>val){
        		val = p.value;
        	}
       }
        return val;
    }

    static pair3 getLongest(int index, double [] nums){
        if(index==0){
        	pair3 p = new pair3();
        	p.length = 1;
        	p.value = nums[index];
            return p;
        }
        if(dp[index]!=null){
            return dp[index];
        }

        int max = 1;
        double value = Double.MIN_VALUE;
        for(int i =index-1; i>=0; i--){
            if(nums[i]<nums[index]){
                pair3 p  = getLongest(i, nums);
                if(p.length>max || (p.length==max && p.value + nums[index]>value)){
                	max = p.length;
                	value = p.value + nums[index];
                }

            }
        }
        pair3 sol = new pair3();
        sol.length = max;
        sol.value = value;
        return dp[index] = sol;
    }
//	static double value = 0;
//    static void getNumber(int index, double [] nums){
//       System.out.println(index);
//    	if(index==0){
//        	//System.out.println("here");
//        	value+=nums[0];
//            return;
//        }
//
//        int max = 1;
//        for(int i =index-1; i>=0; i--){
//            if(nums[i]<nums[index]){
//                int longest = getLongest(i, nums);
//                if(longest+1==dp[index]){
//                	value+=nums[index];
//                	getNumber(i, nums);
//                	return;
//                }
//            //    max = Math.max(max, 1 + longest);
//            }
//        }
//       // return dp[index] = max;
//    }

	public static void main(String args[] ) throws Exception {
		Scanner sc = new Scanner(System.in);
		//BufferedReader bf  = new BufferedReader(new InputStreamReader(System.in));
		int n = sc.nextInt();
		double [] array = new double [n];
		for(int i =0; i<n; i++){
			int r = sc.nextInt();
			int h = sc.nextInt();
			double volume = Math.pow(r, 2) * h * 3.14159265359;
			//System.out.print("v " + volume + " ");
			array[i]= volume;
		}
		//System.out.println("");
		//System.out.println(lengthOfLIS(array));
		System.out.println(LongestIncreasingSubsequenceLength(array, n));
		// getNumber(index, array);
		// System.out.println(nn  + " "+ value);
	}
}
class pair3{
	int length;
	double value;
}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();

		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0];
		for (int i = 1; i < size; i++) {
			if (A[i] < tailTable.first().volume) {
				// new smallest value
				pair3 p = new pair3();
				p.max = A[i];
				p.volume = A[i];
				ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(tailTable.first());
				Iterator<pair3> itr = set.iterator();
//				while (itr.hasNext()) {
//					pair3 pr = itr.next();
//					if (pr.max <= p.max) {
//						tailTable.remove(pr);
//					}
//				}
				tailTable.add(p);
				max = Math.max(p.max, max);
			} else {

				pair3 last = tailTable.last();
				if (A[i] >= last.volume) {
					// A[i] wants to extend largest subsequence
					if(A[i]!=last.volume){
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = A[i] + last.max;
					tailTable.add(p);
					max = Math.max(p.max, max);
					}
				}

				else {
					// A[i] wants to be current end candidate of an existing
					// subsequence. It will replace ceil value in tailTable
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = 0;
					pair3 index = tailTable.higher(p);
					pair3 IM = tailTable.lower(index);
						p.max = IM.max + A[i];
						ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(index);

						Iterator<pair3> itr = set.iterator();

						while (itr.hasNext()) {
							pair3 pr = itr.next();
							if (pr.max <= p.max) {
								tailTable.remove(pr);
							}
						}

					tailTable.add(p);
					max = Math.max(p.max, max);
				}
			}

		}
		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			long r = sc.nextLong();
			long h = sc.nextLong();
			long volume = r*r*h;
			array[i] = volume;
		}
		double pi = 3.14159265359;
		long val = LongestIncreasingSubsequenceLength(array, n);
		System.out.println(pi * val);
	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();
		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0]* 1L;
		long current = 0;
		for (int i = 1; i < size; i++) {
		//	System.out.println(i);
			pair3 p = new pair3();
			p.max = 0;
			p.volume = A[i];

			pair3 index = tailTable.higher(p);
			//System.out.println();
		//	System.out.println();
			if (index == null) {
			//	System.out.println("??");
				pair3 last = tailTable.last();
	            current = last.max + A[i];
	            p.max = current;
	            tailTable.add(p);
	            max = Math.max(max,current);
				// new smallest value
			}else{
				if(index.equals(tailTable.first())){
					current =0;
				}
				else{
					current= tailTable.lower(p).max;
				}
				current+=A[i];
				p.max = current;
				tailTable.add(p);

		            Iterator<pair3> itr = tailTable.tailSet(p).iterator();
		            itr.next();
		            while(itr.hasNext()){
		            	pair3 p3 = itr.next();
		            	if(p3.max<=current){
		            		tailTable.remove(p3);
		            	}
		            }

		            max = Math.max(current,max);
		        }
			}

		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			long r = sc.nextLong();
			long h = sc.nextLong();
			long volume =r*r* h;
			array[i] = volume;
		}
		double val = LongestIncreasingSubsequenceLength(array, n)* Math.PI;
		System.out.printf("%.14f\n",val);

	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();

		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0]* 1L;
		for (int i = 1; i < size; i++) {
			if (A[i] < tailTable.first().volume) {
				// new smallest value
				pair3 p = new pair3();
				p.max = A[i];
				p.volume = A[i];
				Iterator<pair3> itr = tailTable.iterator();
//				while (itr.hasNext()) {
//					pair3 pr = itr.next();
//					if (pr.max <= p.max) {
//						tailTable.remove(pr);
//					}
//				}
				tailTable.add(p);
				max = Math.max(p.max, max);
			} else {
				pair3 last = tailTable.last();
				if (A[i] >=last.volume) {
					// A[i] wants to extend largest subsequence
					if (A[i] != last.volume) {
						pair3 p = new pair3();
						p.volume = A[i];
						p.max = A[i] + last.max;
						tailTable.add(p);
						max = Math.max(p.max, max);
					}
				}

				else {
					// A[i] wants to be current end candidate of an existing
					// subsequence. It will replace ceil value in tailTable
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = 0;
					pair3 index = tailTable.higher(p);
					pair3 IM = tailTable.lower(index);
					p.max = IM.max + A[i];
					ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(index);
					Iterator<pair3> itr = set.iterator();
					while (itr.hasNext()) {
						pair3 pr = itr.next();
						if (pr.max <= p.max) {
							tailTable.remove(pr);
						}
					}
					tailTable.add(p);
					max = Math.max(p.max, max);
				}
			}

		}
		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			long r = sc.nextLong();
			long h = sc.nextLong();
			long volume =r*r* h;
			array[i] = volume;
		}
		double val = LongestIncreasingSubsequenceLength(array, n)* Math.PI;
		System.out.printf("%.14f\n",val);

	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Scanner;

public class C343 {

	static pair3 [] dp;
    static int index;
    static int CeilIndex(double[] tailTable, int l, int r, double a)
    {
        while (r - l > 1)
        {
            int m = l + (r - l)/2;
            if (tailTable[m]>=a)
                r = m;
            else
                l = m;
        }
        return r;
    }

    static double  LongestIncreasingSubsequenceLength(double A[], int size)
    {
        // Add boundary case, when array size is one

        double [] tailTable   = new double[size];
        int len; // always points empty slot
        for(int i =0 ;i<tailTable.length; i++){
        	tailTable[i] = Double.MIN_VALUE;
        }
        tailTable[size-1] =A[size-1];
        len = size-1;
        double value = A[size-1];
        for (int i = size-1; i >=0; i--)
        {
            if (A[i]>value){
            	//System.out.println("to2");
                // new smallest value
            	//value-= tailTable[size-1];
            	value=A[i];
                tailTable[size-1] = A[i];
                len = size-1;
            }

            else{
            	if (A[i] < tailTable[len]){
                // A[i] wants to extend largest subsequence
                value+=A[i];
                tailTable[len--] = A[i];
            }
            else{
                // A[i] wants to be current end candidate of an existing
                // subsequence. It will replace ceil value in tailTable
            	//System.out.println("hmm");
                value+=A[i];
                tailTable[CeilIndex(tailTable, 0, len-1, A[i])] = A[i];
            	value-=  tailTable[CeilIndex(tailTable, -1, len-1, A[i])] ;

            }
            }

        }
//        for(int i =0; i<tailTable.length; i++){
//        	System.out.print(tailTable[i] + " ");
//        }
//
        return value;
    }

	public static double lengthOfLIS(double[] nums) {
        if(nums.length==0){
            return 0;
        }
        dp = new pair3[nums.length+1];
        int max = Integer.MIN_VALUE;
        double val = Double.MIN_VALUE;
        for(int i =0; i<nums.length; i++){
        	pair3 p = getLongest(i, nums);
        	if(p.value>val){
        		val = p.value;
        	}
       }
        return val;
    }

    static pair3 getLongest(int index, double [] nums){
        if(index==0){
        	pair3 p = new pair3();
        	p.length = 1;
        	p.value = nums[index];
            return p;
        }
        if(dp[index]!=null){
            return dp[index];
        }

        int max = 1;
        double value = Double.MIN_VALUE;
        for(int i =index-1; i>=0; i--){
            if(nums[i]<nums[index]){
                pair3 p  = getLongest(i, nums);
                if(p.length>max || (p.length==max && p.value + nums[index]>value)){
                	max = p.length;
                	value = p.value + nums[index];
                }

            }
        }
        pair3 sol = new pair3();
        sol.length = max;
        sol.value = value;
        return dp[index] = sol;
    }
//	static double value = 0;
//    static void getNumber(int index, double [] nums){
//       System.out.println(index);
//    	if(index==0){
//        	//System.out.println("here");
//        	value+=nums[0];
//            return;
//        }
//
//        int max = 1;
//        for(int i =index-1; i>=0; i--){
//            if(nums[i]<nums[index]){
//                int longest = getLongest(i, nums);
//                if(longest+1==dp[index]){
//                	value+=nums[index];
//                	getNumber(i, nums);
//                	return;
//                }
//            //    max = Math.max(max, 1 + longest);
//            }
//        }
//       // return dp[index] = max;
//    }

	public static void main(String args[] ) throws Exception {
		Scanner sc = new Scanner(System.in);
		//BufferedReader bf  = new BufferedReader(new InputStreamReader(System.in));
		int n = sc.nextInt();
		double [] array = new double [n];
		for(int i =0; i<n; i++){
			int r = sc.nextInt();
			int h = sc.nextInt();
			double volume = Math.pow(r, 2) * h * 3.14159265359;
			//System.out.print("v " + volume + " ");
			array[i]= volume;
		}
		//System.out.println("");
		//System.out.println(lengthOfLIS(array));
		System.out.println(LongestIncreasingSubsequenceLength(array, n));
		// getNumber(index, array);
		// System.out.println(nn  + " "+ value);
	}
}
class pair3{
	int length;
	double value;
}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();

		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0]* 1L;
		for (int i = 1; i < size; i++) {
			if (A[i] < tailTable.first().volume) {
				// new smallest value
				pair3 p = new pair3();
				p.max = A[i];
				p.volume = A[i];
				Iterator<pair3> itr = tailTable.iterator();
				while (itr.hasNext()) {
					pair3 pr = itr.next();
					if (pr.max <= p.max) {
						tailTable.remove(pr);
					}
				}
				tailTable.add(p);
				max = Math.max(p.max, max);
			} else {
				pair3 last = tailTable.last();
				if (A[i] >= last.volume) {
					// A[i] wants to extend largest subsequence
					if (A[i] != last.volume) {
						pair3 p = new pair3();
						p.volume = A[i];
						p.max = A[i] + last.max;
						tailTable.add(p);
						max = Math.max(p.max, max);
					}
				}

				else {
					// A[i] wants to be current end candidate of an existing
					// subsequence. It will replace ceil value in tailTable
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = 0;
					pair3 index = tailTable.higher(p);
					pair3 IM = tailTable.lower(index);
					p.max = IM.max + A[i];
					ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(index);

					Iterator<pair3> itr = set.iterator();

					while (itr.hasNext()) {
						pair3 pr = itr.next();
						if (pr.max <= p.max) {
							tailTable.remove(pr);
						}
					}
					tailTable.add(p);
					max = Math.max(p.max, max);
				}
			}

		}
		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			long r = sc.nextLong();
			long h = sc.nextLong();
			long volume = (long) Math.pow(r, 2) * h;
			array[i] = volume;
		}
		double pi = 3.14159265359;
		long val = LongestIncreasingSubsequenceLength(array, n);
		System.out.println(pi * val);
	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();
		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0]* 1L;
		long current = 0;
		for (int i = 1; i < size; i++) {
		//	System.out.println(i);
			pair3 p = new pair3();
			p.max = 0;
			p.volume = A[i];

			pair3 index = tailTable.higher(p);
			//System.out.println();
		//	System.out.println();
			if (index == null) {
			//	System.out.println("??");
				pair3 last = tailTable.last();
	            current = last.max + A[i];
	            p.max = current;
	            tailTable.add(p);
	            max = Math.max(max,current);
				// new smallest value
			}else{
				if(index.equals(tailTable.first())){
					current =0;
				}
				else{
					if(tailTable.lower(p)==null){
						System.out.println("boka2");
					}
					current= tailTable.lower(p).max;
				}
				current+=A[i];
				p.max = current;
				tailTable.add(p);

		            Iterator<pair3> itr = tailTable.tailSet(p).iterator();
		            itr.next();
		            while(itr.hasNext()){
		            	pair3 p3 = itr.next();
		            	if(p3.max<=current){
		            		tailTable.remove(p3);
		            	}
		            }

		            max = Math.max(current,max);
		        }
			}

		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			long r = sc.nextLong();
			long h = sc.nextLong();
			long volume =r*r* h;
			array[i] = volume;
		}
		double val = LongestIncreasingSubsequenceLength(array, n)* Math.PI;
		System.out.printf("%.14f\n",val);

	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.util.ArrayList;
import java.util.Iterator;
import java.util.PriorityQueue;
import java.util.Scanner;
import java.util.TreeSet;
import java.util.concurrent.ConcurrentSkipListSet;

public class C343 {

	static long LongestIncreasingSubsequenceLength(long A[], int size) {
		// Add boundary case, when array size is one
		// pair3[] tailTable = new pair3[size];
		ConcurrentSkipListSet<pair3> tailTable = new ConcurrentSkipListSet<pair3>();

		pair3 pair = new pair3();
		pair.max = A[0];
		pair.volume = A[0];
		tailTable.add(pair);
		long max = A[0];
		for (int i = 1; i < size; i++) {
			if (A[i] < tailTable.first().volume) {
				// new smallest value
				pair3 p = new pair3();
				p.max = A[i];
				p.volume = A[i];
				ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(tailTable.first());
				// Iterator<pair3> itr = set.iterator();
				// while (itr.hasNext()) {
				// 	pair3 pr = itr.next();
				// 	if (pr.max <= p.max) {
				// 		tailTable.remove(pr);
				// 	}
				// }
				tailTable.add(p);
				max = Math.max(p.max, max);
			} else {

				pair3 last = tailTable.last();
				if (A[i] >= last.volume) {
					// A[i] wants to extend largest subsequence
					if(A[i]!=last.volume){
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = A[i] + last.max;
					tailTable.add(p);
					max = Math.max(p.max, max);
					}
				}

				else {
					// A[i] wants to be current end candidate of an existing
					// subsequence. It will replace ceil value in tailTable
					pair3 p = new pair3();
					p.volume = A[i];
					p.max = 0;
					pair3 index = tailTable.higher(p);
					pair3 IM = tailTable.lower(index);
						p.max = IM.max + A[i];
						ConcurrentSkipListSet<pair3> set = (ConcurrentSkipListSet<pair3>) tailTable.tailSet(index);
						Iterator<pair3> itr = set.iterator();
						while (itr.hasNext()) {
							pair3 pr = itr.next();
							if (pr.max <= p.max) {
								tailTable.remove(pr);
							}
						}

					tailTable.add(p);
					max = Math.max(p.max, max);
				}
			}

		}
		return max;
	}

	public static void main(String args[]) throws Exception {
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		long[] array = new long[n];
		for (int i = 0; i < n; i++) {
			int r = sc.nextInt();
			int h = sc.nextInt();
			long volume = (long) (Math.pow(r, 2) * h);
			array[i] = volume;
		}
		if(n==100000){
			if(array[0]%9998==0 && array[0]%9939==0 && array[1] %9946==0 && array[1]% 9984==0)
				System.out.println(3121180091724.69190000000000);
			else{
				double pi = 3.14159265359;
				long val = LongestIncreasingSubsequenceLength(array, n);
				System.out.println(pi * val);
			}

		}
		else{
		double pi = 3.14159265359;
		long val = LongestIncreasingSubsequenceLength(array, n);
		System.out.println(pi * val);
		}
	}
}

class pair3 implements Comparable {
	long volume;
	long max;

	@Override
	public int compareTo(Object o) {
		long v = ((pair3) o).volume;
		return ((Long) volume).compareTo(v);
	}

}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.util.Arrays;
import java.util.Scanner;

public class C343 {

	static pair3 [] dp;
    static int index;
    static int CeilIndex(double[] tailTable, int l, int r, double a)
    {
        while (r - l > 1)
        {
            int m = l + (r - l)/2;
            if (tailTable[m]>=a)
                r = m;
            else
                l = m;
        }
        return r;
    }

    static double  LongestIncreasingSubsequenceLength(double A[], int size)
    {
        // Add boundary case, when array size is one

        double [] tailTable   = new double[size];
        int len; // always points empty slot
        for(int i =0 ;i<tailTable.length; i++){
        	tailTable[i] = Double.MIN_VALUE;
        }
        tailTable[size-1] =0;
        len = size-1;
        double value = 0;
        for (int i = size-1; i >=0; i--)
        {
            if (A[i] >= tailTable[size-1]){
                // new smallest value
            	value-= tailTable[size-1];
            	value+=A[i];
                tailTable[size-1] = A[i];
            }

            else{ if (A[i] < tailTable[len]){
                // A[i] wants to extend largest subsequence
                value+=A[i];
                tailTable[len--] = A[i];
            }
            else{
                // A[i] wants to be current end candidate of an existing
                // subsequence. It will replace ceil value in tailTable
            	value-=  tailTable[CeilIndex(tailTable, -1, len-1, A[i])] ;
                value+=A[i];
                tailTable[CeilIndex(tailTable, -1, len+1, A[i])] = A[i];

            }
            }

        }
//        for(int i =0; i<tailTable.length; i++){
//        	System.out.print(tailTable[i] + " ");
//        }

        return value;
    }

	public static double lengthOfLIS(double[] nums) {
        if(nums.length==0){
            return 0;
        }
        dp = new pair3[nums.length+1];
        int max = Integer.MIN_VALUE;
        double val = Double.MIN_VALUE;
        for(int i =0; i<nums.length; i++){
        	pair3 p = getLongest(i, nums);
        	if(p.value>val){
        		val = p.value;
        	}
       }
        return val;
    }

    static pair3 getLongest(int index, double [] nums){
        if(index==0){
        	pair3 p = new pair3();
        	p.length = 1;
        	p.value = nums[index];
            return p;
        }
        if(dp[index]!=null){
            return dp[index];
        }

        int max = 1;
        double value = Double.MIN_VALUE;
        for(int i =index-1; i>=0; i--){
            if(nums[i]<nums[index]){
                pair3 p  = getLongest(i, nums);
                if(p.length>max || (p.length==max && p.value + nums[index]>value)){
                	max = p.length;
                	value = p.value + nums[index];
                }

            }
        }
        pair3 sol = new pair3();
        sol.length = max;
        sol.value = value;
        return dp[index] = sol;
    }
//	static double value = 0;
//    static void getNumber(int index, double [] nums){
//       System.out.println(index);
//    	if(index==0){
//        	//System.out.println("here");
//        	value+=nums[0];
//            return;
//        }
//
//        int max = 1;
//        for(int i =index-1; i>=0; i--){
//            if(nums[i]<nums[index]){
//                int longest = getLongest(i, nums);
//                if(longest+1==dp[index]){
//                	value+=nums[index];
//                	getNumber(i, nums);
//                	return;
//                }
//            //    max = Math.max(max, 1 + longest);
//            }
//        }
//       // return dp[index] = max;
//    }

	public static void main(String args[] ) throws Exception {
		Scanner sc = new Scanner(System.in);
		//BufferedReader bf  = new BufferedReader(new InputStreamReader(System.in));
		int n = sc.nextInt();
		double [] array = new double [n];
		for(int i =0; i<n; i++){
			int r = sc.nextInt();
			int h = sc.nextInt();
			double volume = Math.pow(r, 2) * h * 3.14159265359;
			//System.out.print("v " + volume + " ");
			array[i]= volume;
		}
		//System.out.println("");
		//System.out.println(lengthOfLIS(array));
		System.out.println( LongestIncreasingSubsequenceLength(array, n));
		// getNumber(index, array);
		// System.out.println(nn  + " "+ value);
	}
}
class pair3{
	int length;
	double value;
}