package Round343;

import java.util.Scanner;
import java.util.TreeSet;

public class Main {
	public static class Node{
		Node left;
		Node right;
		Node parent;
		double value;
		int index;
		int countLeft;
		int countRight;
		public Node(double value, int index, Node parent,int countLeft,int countRight){
			this.index = index;
			this.value = value;
			this.parent = parent;
			this.countLeft = countLeft;
			this.countRight = countRight;
		}
	}
	public static class BST{
		Node root;
		public BST(double value, int index){
			root = new Node(value, index,null,0,0);
		}
		public int insert(double value, int index, Node curr, Node notBalanced, int lastGreater){
			System.out.println(curr.value);
			System.out.println("left count = " + curr.countLeft);
			System.out.println("right count = " + curr.countRight);
			if(value >= curr.value){
				curr.countRight++;
				if(curr.countRight > curr.countLeft + 1){
					notBalanced.left = curr.left;
					notBalanced.right = curr.right;
					notBalanced.parent = curr.parent;
					notBalanced.index = curr.index;
					notBalanced.value = curr.value;
					notBalanced.countLeft = curr.countLeft;
					notBalanced.countRight = curr.countRight;
				}
				if(curr.right == null){
					curr.right = new Node(value,index,curr,0,0);
					return lastGreater;
				}
				else{
					return insert(value,index,curr.right,notBalanced,lastGreater);
				}
			}
			else{
				curr.countLeft++;
				if(curr.countLeft > curr.countRight + 1){
					notBalanced.left = curr.left;
					notBalanced.right = curr.right;
					notBalanced.parent = curr.parent;
					notBalanced.index = curr.index;
					notBalanced.value = curr.value;
					notBalanced.countLeft = curr.countLeft;
					notBalanced.countRight = curr.countRight;
				}
				if(curr.left == null){
					curr.left = new Node(value,index,curr,0,0);
					return curr.index;
				}
				else{
					return insert(value,index,curr.left,notBalanced,curr.index);
				}
			}
		}
		public Node getLeftMost(Node n,Node notBalanced){
			int val = 1 + notBalanced.countLeft;
			System.out.println("val = " + val);
			n.countLeft += val;
			while(n.left != null){
				n = n.left;
				n.countLeft += val;
			}
			return n;
		}
		public Node getRightMost(Node n,Node notBalanced){
			int val = 1 + notBalanced.countRight;
			System.out.println("val = " + val);
			n.countRight += val;
			while(n.right != null){
				n = n.right;
				n.countRight += val;
			}
			return n;
		}
		public void balance(Node n){
			if(n.countLeft > n.countRight){
				if(n.parent == null){
					Node left = n.left;
					Node rightMost = getRightMost(left,n);
					rightMost.right = n;
					left.parent = null;
					root = left;
					n.parent = rightMost;
					n.left = null;
				}
				else if(n.parent.left != null && n.parent.left.index == n.index){
					n.parent.left = n.left;
					Node left = n.left;
					Node rightMost = getRightMost(left,n);
					rightMost.right = n;
					left.parent = n.parent;
					n.parent = rightMost;
					n.left = null;
				}
				else{
					n.parent.right = n.right;
					Node left = n.left;
					Node rightMost = getRightMost(left,n);
					rightMost.right = n;
					left.parent = n.parent;
					n.parent = rightMost;
					n.left = null;
				}
				n.countLeft = 0;
			}
			else{
				if(n.parent == null){
					Node right = n.right;
					Node leftMost = getLeftMost(right,n);
					leftMost.left = n;
					right.parent = null;
					root = right;
					n.parent = leftMost;
					n.right = null;
				}
				else if(n.parent.right != null && n.parent.right.index == n.index){
					n.parent.right = n.right;
					Node right = n.right;
					Node leftMost = getLeftMost(right,n);
					leftMost.left = n;
					right.parent = n.parent;
					n.parent = leftMost;
					n.right = null;
				}
				else{
					n.parent.left = n.left;
					Node right = n.right;
					Node leftMost = getLeftMost(right,n);
					leftMost.left = n;
					right.parent = n.parent;
					n.parent = leftMost;
					n.right = null;
				}
				n.countRight = 0;
			}
		}
		public int insertHelper(double value, int index, Node curr, Node notBalanced, int lastGreater){
			int result = insert(value, index, curr, notBalanced, lastGreater);
			if(notBalanced.index != -1){
				System.out.println("BALANCE: " + notBalanced.value);
				balance(notBalanced);
			}
			return result;
		}
	}
	public static class Pair implements Comparable<Pair>{
		double value;
		int index;
		public Pair(int index, double value){
			this.index = index;
			this.value = value;
		}
		@Override
		public int compareTo(Pair o) {
			return Double.compare(this.value, o.value);
		}
		@Override
		public boolean equals(Object o){
			return this.index == ((Pair)o).index && this.value == ((Pair)o).value;
		}
	}
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		double[] volume = new double[n];
		for(int i=0;i<n;i++){
			double r = sc.nextDouble();
			double h = sc.nextDouble();
			volume[i] = Math.PI * r * r * h;
		}
		TreeSet<Pair> set = new TreeSet<Pair>();
		double[] dp = new double[n];
		dp[n-1] = volume[n-1];
		set.add(new Pair(n-1,volume[n-1]));
		for(int i=n-2;i>=0;i--){
			Pair higher = set.higher(new Pair(i,volume[i]));
			if(higher != null){
				dp[i] = dp[higher.index];
			}
			dp[i] += volume[i];
			Pair pos = set.floor(new Pair(i,volume[i]));
			while(pos != null && dp[pos.index] <= dp[i]){
				set.remove(pos);
				pos = set.floor(new Pair(i,volume[i]));
			}
			set.add(new Pair(i,volume[i]));
		}
		double max = 0;
		for(int i=0;i<dp.length;i++){
			max = dp[i] > max ? dp[i] : max;
		}
		System.out.println(max);
	}
}


import java.util.Scanner;
import java.util.TreeSet;

public class Main {
	public static class Node{
		Node left;
		Node right;
		Node parent;
		double value;
		int index;
		int countLeft;
		int countRight;
		public Node(double value, int index, Node parent,int countLeft,int countRight){
			this.index = index;
			this.value = value;
			this.parent = parent;
			this.countLeft = countLeft;
			this.countRight = countRight;
		}
	}
	public static class BST{
		Node root;
		public BST(double value, int index){
			root = new Node(value, index,null,0,0);
		}
		public int insert(double value, int index, Node curr, Node notBalanced, int lastGreater){
			System.out.println(curr.value);
			System.out.println("left count = " + curr.countLeft);
			System.out.println("right count = " + curr.countRight);
			if(value >= curr.value){
				curr.countRight++;
				if(curr.countRight > curr.countLeft + 1){
					notBalanced.left = curr.left;
					notBalanced.right = curr.right;
					notBalanced.parent = curr.parent;
					notBalanced.index = curr.index;
					notBalanced.value = curr.value;
					notBalanced.countLeft = curr.countLeft;
					notBalanced.countRight = curr.countRight;
				}
				if(curr.right == null){
					curr.right = new Node(value,index,curr,0,0);
					return lastGreater;
				}
				else{
					return insert(value,index,curr.right,notBalanced,lastGreater);
				}
			}
			else{
				curr.countLeft++;
				if(curr.countLeft > curr.countRight + 1){
					notBalanced.left = curr.left;
					notBalanced.right = curr.right;
					notBalanced.parent = curr.parent;
					notBalanced.index = curr.index;
					notBalanced.value = curr.value;
					notBalanced.countLeft = curr.countLeft;
					notBalanced.countRight = curr.countRight;
				}
				if(curr.left == null){
					curr.left = new Node(value,index,curr,0,0);
					return curr.index;
				}
				else{
					return insert(value,index,curr.left,notBalanced,curr.index);
				}
			}
		}
		public Node getLeftMost(Node n,Node notBalanced){
			int val = 1 + notBalanced.countLeft;
			System.out.println("val = " + val);
			n.countLeft += val;
			while(n.left != null){
				n = n.left;
				n.countLeft += val;
			}
			return n;
		}
		public Node getRightMost(Node n,Node notBalanced){
			int val = 1 + notBalanced.countRight;
			System.out.println("val = " + val);
			n.countRight += val;
			while(n.right != null){
				n = n.right;
				n.countRight += val;
			}
			return n;
		}
		public void balance(Node n){
			if(n.countLeft > n.countRight){
				if(n.parent == null){
					Node left = n.left;
					Node rightMost = getRightMost(left,n);
					rightMost.right = n;
					left.parent = null;
					root = left;
					n.parent = rightMost;
					n.left = null;
				}
				else if(n.parent.left != null && n.parent.left.index == n.index){
					n.parent.left = n.left;
					Node left = n.left;
					Node rightMost = getRightMost(left,n);
					rightMost.right = n;
					left.parent = n.parent;
					n.parent = rightMost;
					n.left = null;
				}
				else{
					n.parent.right = n.right;
					Node left = n.left;
					Node rightMost = getRightMost(left,n);
					rightMost.right = n;
					left.parent = n.parent;
					n.parent = rightMost;
					n.left = null;
				}
				n.countLeft = 0;
			}
			else{
				if(n.parent == null){
					Node right = n.right;
					Node leftMost = getLeftMost(right,n);
					leftMost.left = n;
					right.parent = null;
					root = right;
					n.parent = leftMost;
					n.right = null;
				}
				else if(n.parent.right != null && n.parent.right.index == n.index){
					n.parent.right = n.right;
					Node right = n.right;
					Node leftMost = getLeftMost(right,n);
					leftMost.left = n;
					right.parent = n.parent;
					n.parent = leftMost;
					n.right = null;
				}
				else{
					n.parent.left = n.left;
					Node right = n.right;
					Node leftMost = getLeftMost(right,n);
					leftMost.left = n;
					right.parent = n.parent;
					n.parent = leftMost;
					n.right = null;
				}
				n.countRight = 0;
			}
		}
		public int insertHelper(double value, int index, Node curr, Node notBalanced, int lastGreater){
			int result = insert(value, index, curr, notBalanced, lastGreater);
			if(notBalanced.index != -1){
				System.out.println("BALANCE: " + notBalanced.value);
				balance(notBalanced);
			}
			return result;
		}
	}
	public static class Pair implements Comparable<Pair>{
		double value;
		int index;
		public Pair(int index, double value){
			this.index = index;
			this.value = value;
		}
		@Override
		public int compareTo(Pair o) {
			return Double.compare(this.value, o.value);
		}
		@Override
		public boolean equals(Object o){
			return this.index == ((Pair)o).index && this.value == ((Pair)o).value;
		}
	}
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		double[] volume = new double[n];
		for(int i=0;i<n;i++){
			double r = sc.nextDouble();
			double h = sc.nextDouble();
			volume[i] = r * r * h;
		}
		TreeSet<Pair> set = new TreeSet<Pair>();
		double[] dp = new double[n];
		dp[n-1] = volume[n-1];
		set.add(new Pair(n-1,volume[n-1]));
		for(int i=n-2;i>=0;i--){
			Pair higher = set.higher(new Pair(i,volume[i]));
			if(higher != null){
				dp[i] = dp[higher.index];
			}
			dp[i] += volume[i];
			Pair pos = set.floor(new Pair(i,volume[i]));
			while(pos != null && dp[pos.index] <= dp[i]){
				set.remove(pos);
				pos = set.floor(new Pair(i,volume[i]));
			}
			set.add(new Pair(i,volume[i]));
		}
		double max = 0;
		for(int i=0;i<dp.length;i++){
			max = dp[i] > max ? dp[i] : max;
		}
		System.out.println(Math.PI*max);
	}
}


import java.util.Scanner;

public class Main {
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		double[] volume = new double[n];
		for(int i=0;i<n;i++){
			double r = sc.nextDouble();
			double h = sc.nextDouble();
			volume[i] = Math.PI * r * r * h;
		}
		int[] firstGreater = new int[n];
		double[] maxVolume = new double[n];
		firstGreater[n-1] = n;
		maxVolume[n-1] = volume[n-1];
		for(int i=n-2;i>=0;i--){
			int j = i+1;
			while(j != n && volume[j] <= volume[i]){
				j = firstGreater[j];
			}
			firstGreater[i] = j;
			if(j == n){
				maxVolume[i] = volume[i];
			}
			else{
				maxVolume[i] = volume[i] + maxVolume[j];
			}
		}
		double max = 0;
		for(int i=0;i<maxVolume.length;i++){
			max = maxVolume[i] > max ? maxVolume[i] : max;
		}
		System.out.println(max);
	}
}


import java.util.Scanner;
import java.util.TreeSet;

public class Main {
	public static class Node{
		Node left;
		Node right;
		Node parent;
		double value;
		int index;
		int countLeft;
		int countRight;
		public Node(double value, int index, Node parent,int countLeft,int countRight){
			this.index = index;
			this.value = value;
			this.parent = parent;
			this.countLeft = countLeft;
			this.countRight = countRight;
		}
	}
	public static class BST{
		Node root;
		public BST(double value, int index){
			root = new Node(value, index,null,0,0);
		}
		public int insert(double value, int index, Node curr, Node notBalanced, int lastGreater){
			System.out.println(curr.value);
			System.out.println("left count = " + curr.countLeft);
			System.out.println("right count = " + curr.countRight);
			if(value >= curr.value){
				curr.countRight++;
				if(curr.countRight > curr.countLeft + 1){
					notBalanced.left = curr.left;
					notBalanced.right = curr.right;
					notBalanced.parent = curr.parent;
					notBalanced.index = curr.index;
					notBalanced.value = curr.value;
					notBalanced.countLeft = curr.countLeft;
					notBalanced.countRight = curr.countRight;
				}
				if(curr.right == null){
					curr.right = new Node(value,index,curr,0,0);
					return lastGreater;
				}
				else{
					return insert(value,index,curr.right,notBalanced,lastGreater);
				}
			}
			else{
				curr.countLeft++;
				if(curr.countLeft > curr.countRight + 1){
					notBalanced.left = curr.left;
					notBalanced.right = curr.right;
					notBalanced.parent = curr.parent;
					notBalanced.index = curr.index;
					notBalanced.value = curr.value;
					notBalanced.countLeft = curr.countLeft;
					notBalanced.countRight = curr.countRight;
				}
				if(curr.left == null){
					curr.left = new Node(value,index,curr,0,0);
					return curr.index;
				}
				else{
					return insert(value,index,curr.left,notBalanced,curr.index);
				}
			}
		}
		public Node getLeftMost(Node n,Node notBalanced){
			int val = 1 + notBalanced.countLeft;
			System.out.println("val = " + val);
			n.countLeft += val;
			while(n.left != null){
				n = n.left;
				n.countLeft += val;
			}
			return n;
		}
		public Node getRightMost(Node n,Node notBalanced){
			int val = 1 + notBalanced.countRight;
			System.out.println("val = " + val);
			n.countRight += val;
			while(n.right != null){
				n = n.right;
				n.countRight += val;
			}
			return n;
		}
		public void balance(Node n){
			if(n.countLeft > n.countRight){
				if(n.parent == null){
					Node left = n.left;
					Node rightMost = getRightMost(left,n);
					rightMost.right = n;
					left.parent = null;
					root = left;
					n.parent = rightMost;
					n.left = null;
				}
				else if(n.parent.left != null && n.parent.left.index == n.index){
					n.parent.left = n.left;
					Node left = n.left;
					Node rightMost = getRightMost(left,n);
					rightMost.right = n;
					left.parent = n.parent;
					n.parent = rightMost;
					n.left = null;
				}
				else{
					n.parent.right = n.right;
					Node left = n.left;
					Node rightMost = getRightMost(left,n);
					rightMost.right = n;
					left.parent = n.parent;
					n.parent = rightMost;
					n.left = null;
				}
				n.countLeft = 0;
			}
			else{
				if(n.parent == null){
					Node right = n.right;
					Node leftMost = getLeftMost(right,n);
					leftMost.left = n;
					right.parent = null;
					root = right;
					n.parent = leftMost;
					n.right = null;
				}
				else if(n.parent.right != null && n.parent.right.index == n.index){
					n.parent.right = n.right;
					Node right = n.right;
					Node leftMost = getLeftMost(right,n);
					leftMost.left = n;
					right.parent = n.parent;
					n.parent = leftMost;
					n.right = null;
				}
				else{
					n.parent.left = n.left;
					Node right = n.right;
					Node leftMost = getLeftMost(right,n);
					leftMost.left = n;
					right.parent = n.parent;
					n.parent = leftMost;
					n.right = null;
				}
				n.countRight = 0;
			}
		}
		public int insertHelper(double value, int index, Node curr, Node notBalanced, int lastGreater){
			int result = insert(value, index, curr, notBalanced, lastGreater);
			if(notBalanced.index != -1){
				System.out.println("BALANCE: " + notBalanced.value);
				balance(notBalanced);
			}
			return result;
		}
	}
	public static class Pair implements Comparable<Pair>{
		double value;
		int index;
		public Pair(int index, double value){
			this.index = index;
			this.value = value;
		}
		@Override
		public int compareTo(Pair o) {
			return Double.compare(this.value, o.value);
		}
		@Override
		public boolean equals(Object o){
			return this.index == ((Pair)o).index && this.value == ((Pair)o).value;
		}
	}
	public static void main(String[] args){
		Scanner sc = new Scanner(System.in);
		int n = sc.nextInt();
		double[] volume = new double[n];
		for(int i=0;i<n;i++){
			double r = sc.nextDouble();
			double h = sc.nextDouble();
			volume[i] = Math.PI * r * r * h;
		}
		TreeSet<Pair> set = new TreeSet<Pair>();
		double[] dp = new double[n];
		dp[n-1] = volume[n-1];
		set.add(new Pair(n-1,volume[n-1]));
		for(int i=n-2;i>=0;i--){
			Pair higher = set.higher(new Pair(i,volume[i]));
			if(higher != null){
				dp[i] = dp[higher.index];
			}
			dp[i] += volume[i];
			Pair pos = set.floor(new Pair(i,volume[i]));
			while(pos != null && dp[pos.index] <= dp[i]){
				set.remove(pos);
				pos = set.floor(new Pair(i,volume[i]));
			}
			set.add(new Pair(i,volume[i]));
		}
		double max = 0;
		for(int i=0;i<dp.length;i++){
			max = dp[i] > max ? dp[i] : max;
		}
		System.out.println(max);
	}
}


import java.io.*;
import java.util.*;
public class D629 {
public static void main(String[] args) throws IOException {
	input.init(System.in);
	PrintWriter out = new PrintWriter(System.out);
	int n = input.nextInt();
	long[] vs = new long[n];
	TreeSet<Long> set = new TreeSet<Long>();
	for(int i = 0; i<n; i++)
	{
		long r = input.nextLong(), h = input.nextLong();
		vs[i] = r*r*h;
		set.add(vs[i]);
	}
	HashMap<Long, Integer> map = new HashMap<Long, Integer>();
	int idx = 0;
	long[] dp = new long[n];
	for(long x : set) map.put(x, idx++);
	IT it = new IT(n);
	long res = 0;
	for(int i = 0; i<n; i++)
	{
		long max = 0;
		int v = map.get(vs[i]);
		max = Math.max(max, it.get(0,v-1));
		dp[i] = max + vs[i];
		res = Math.max(res, dp[i]);
		it.add(v, v, dp[i]);
	}
	out.println(res*Math.PI);
	out.close();
}
static class IT
{
int[] left,right, a, b;
long[] val, prop;
IT(int n)
{
	left = new int[4*n];
	right = new int[4*n];
	val = new long[4*n];
	prop = new long[4*n];
	a = new int[4*n];
	b = new int[4*n];
	init(0,0, n-1);
}
int init(int at, int l, int r)
{
	a[at] = l;
	b[at] = r;
	if(l==r)
		left[at] = right [at] = -1;
	else
	{
		int mid = (l+r)/2;
		left[at] = init(2*at+1,l,mid);
		right[at] = init(2*at+2,mid+1,r);
	}
	return at++;
}
long get(int x, int y)
{
	return go(x,y, 0);
}
void push(int at)
{
	if(prop[at] != 0)
	{
		go3(a[left[at]], b[left[at]], prop[at], left[at]);
		go3(a[right[at]], b[right[at]], prop[at], right[at]);
		prop[at] = 0;
	}
}
long go(int x,int y, int at)
{
	if(at==-1 || y<a[at] || x>b[at]) return -987654321;
	if(x <= a[at] && y>= b[at]) return val[at];
	push(at);
	return Math.max(go(x, y, left[at]), go(x, y, right[at]));
}
//add v to elements x through y
void add(int x, int y, long v)
{
	go3(x, y, v, 0);
}
void go3(int x, int y, long v, int at)
{
	if(at==-1) return;
	if(y < a[at] || x > b[at]) return;
	x = Math.max(x, a[at]);
	y = Math.min(y, b[at]);
	if(y == b[at] && x == a[at])
	{
		val[at] = v;
		prop[at] = v;
		return;
	}
	push(at);
	go3(x, y, v, left[at]);
	go3(x, y, v, right[at]);
	val[at] = Math.max(val[left[at]], val[right[at]]);
}
}
public static class input {
	static BufferedReader reader;
	static StringTokenizer tokenizer;

	static void init(InputStream input) {
		reader = new BufferedReader(new InputStreamReader(input));
		tokenizer = new StringTokenizer("");
	}

	static String next() throws IOException {
		while (!tokenizer.hasMoreTokens())
			tokenizer = new StringTokenizer(reader.readLine());
		return tokenizer.nextToken();
	}

	static int nextInt() throws IOException {
		return Integer.parseInt(next());
	}

	static double nextDouble() throws IOException {
		return Double.parseDouble(next());
	}

	static long nextLong() throws IOException {
		return Long.parseLong(next());
	}
}
}


import java.util.*;
public class Main {
	public static void main(String[] args) {
		Scanner stdin = new Scanner(System.in);
		int n = stdin.nextInt();
		Cake[] cake = new Cake[n];
		for (int i = 0; i < n; i++) {
			long r = stdin.nextInt();
			long h = stdin.nextInt();
			cake[i] = new Cake(r * r * h, i + 1);
		}
		SegTree sTree = new SegTree(n);
		Arrays.sort(cake, 0, n);

		for (int i = 0; i < n; i++) {
			long sum = sTree.query(1, 1, cake[i].id);
			sTree.update(1, cake[i].id, sum + cake[i].v);
		}

		System.out.printf("%.9f", sTree.query(1, 1, n) * Math.PI);
		System.out.println();
	}
}

class SegTree {
	class Node{
		int l;
		int r;
		long sum;
		Node(int l, int r, long sum) {
			this.l = l;
			this.r = r;
			this.sum = sum;
		}
	}
	Node[] node;
	SegTree(int n) {
		node = new Node[4 * n + 10];
		build(1, 1, n);
	}
	void build(int id, int left, int right) {
		node[id] = new Node(left, right, 0);
		if (left < right) {
			int mid = (left + right) >> 1;
			build(id * 2, left, mid);
			build(id * 2 + 1, mid + 1, right);
		}
	}

	void update(int id, int pos, long val) {
		int le = node[id].l;
		int ri = node[id].r;
		if (le == ri) {
			node[id].sum = Math.max(node[id].sum, val);
			return;
		}
		int mid = (le + ri) >> 1;
		if (pos <= mid) update(id * 2, pos, val);
		else update(id * 2 + 1, pos, val);
		node[id].sum = Math.max(node[id].sum, node[id * 2].sum);
		node[id].sum = Math.max(node[id].sum, node[id * 2 + 1].sum);
	}

	long query(int id, int le, int ri) {
		if (le > ri) return 0;
		if (le == node[id].l && node[id].r == ri)
			return node[id].sum;
		int mid = (node[id].l + node[id].r) >> 1;
		long res1 = query(id * 2, le, Math.min(ri, mid));
		long res2 = query(id * 2 + 1, Math.max(le, mid + 1), ri);
		return Math.max(res1, res2);
	}
}

class Cake implements Comparable<Cake>{
	long v;
	int id;
	Cake(long v, int id) {
		this.v = v;
		this.id = id;
	}
	public int compareTo(Cake that) {
		if (this.v == that.v)
			return that.id - this.id;
		return (this.v < that.v) ? -1 : 1;
	}
}


import java.util.*;
public class Main {
	public static void main(String[] args) {
		Scanner stdin = new Scanner(System.in);
		int n = stdin.nextInt();
		Cake[] cake = new Cake[n];
		for (int i = 0; i < n; i++) {
			int r = stdin.nextInt();
			int h = stdin.nextInt();
			cake[i] = new Cake(r * r * h, i + 1);
		}
		SegTree sTree = new SegTree(n);
		Arrays.sort(cake, 0, n);

		for (int i = 0; i < n; i++) {
			long sum = sTree.query(1, 1, cake[i].id);
			sTree.update(1, cake[i].id, sum + cake[i].v);
		}

		System.out.printf("%.9f", sTree.query(1, 1, n) * Math.PI);
		System.out.println();
	}
}

class SegTree {
	class Node{
		int l;
		int r;
		long sum;
		Node(int l, int r, long sum) {
			this.l = l;
			this.r = r;
			this.sum = sum;
		}
	}
	Node[] node;
	SegTree(int n) {
		node = new Node[4 * n + 10];
		build(1, 1, n);
	}
	void build(int id, int left, int right) {
		node[id] = new Node(left, right, 0);
		if (left < right) {
			int mid = (left + right) >> 1;
			build(id * 2, left, mid);
			build(id * 2 + 1, mid + 1, right);
		}
	}

	void update(int id, int pos, long val) {
		int le = node[id].l;
		int ri = node[id].r;
		if (le == ri) {
			node[id].sum = Math.max(node[id].sum, val);
			return;
		}
		int mid = (le + ri) >> 1;
		if (pos <= mid) update(id * 2, pos, val);
		else update(id * 2 + 1, pos, val);
		node[id].sum = Math.max(node[id].sum, node[id * 2].sum);
		node[id].sum = Math.max(node[id].sum, node[id * 2 + 1].sum);
	}

	long query(int id, int le, int ri) {
		if (le > ri) return 0;
		if (le == node[id].l && node[id].r == ri)
			return node[id].sum;
		int mid = (node[id].l + node[id].r) >> 1;
		long res1 = query(id * 2, le, Math.min(ri, mid));
		long res2 = query(id * 2 + 1, Math.max(le, mid + 1), ri);
		return Math.max(res1, res2);
	}
}

class Cake implements Comparable<Cake>{
	long v;
	int id;
	Cake(long v, int id) {
		this.v = v;
		this.id = id;
	}
	public int compareTo(Cake that) {
		if (this.v == that.v)
			return that.id - this.id;
		return (this.v < that.v) ? -1 : 1;
	}
}


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

public class Main {

	public static void main(String[] args) {

		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		solve(in, out);
		out.close();
	}

	private static void solve(InputReader in, PrintWriter out) {

		int N = in.nextInt();
		long[] tab = new long[N];
		for (int i = 0; i < N; i++) {
			long ri = in.nextLong();
			long hi = in.nextLong();
			tab[i] = ri * ri * hi;
		}

		int[] M = new int[N + 1];
		long[] partResult = new long[N + 1];

		M[0] = 0;
		M[1] = 0;
		partResult[1] = tab[0];
		int longest = 1;

		for (int i = 1; i < N; i++) {
			long curr = tab[i];
			int index = binarySearch(M, tab, curr, 1, longest);

			if(tab[M[index]] < curr) {
				partResult[index + 1] = partResult[index] + curr;
				M[index + 1] = i;
				longest++;
			} else if (index > 0 && partResult[index] < partResult[index - 1] + curr ) {
				partResult[index] = partResult[index -1 ] + curr;
				M[index] = i;
			}
		}

		long res = 0;
		for (int i = 0; i < partResult.length; i++) {
			res = Math.max(res, partResult[i]);
		}
		out.println(res * Math.PI);
	}

	private static int binarySearch(int[] M, long[] tab, long curr, int left, int right) {

		if (left == right) {
			return left;
		}
		int middle = left + (right - left) / 2;

		if (tab[M[middle]] < curr) {
			left = middle + 1;
		} else {
			right = middle;
		}

		return binarySearch(M, tab, curr, left, right);
	}

	/*
	 *
	 */
	// --------------------------------------------------------
	static class InputReader {
		public BufferedReader reader;
		public StringTokenizer tokenizer;

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

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

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

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

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

		public String nextLine() {
			String str = "";
			try {
				str = reader.readLine();
			} catch (IOException e) {
				e.printStackTrace();
			}

			return str;
		}
	}
}


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

public class Main {

	public static void main(String[] args) {

		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		solve(in, out);
		out.close();
	}

	private static void solve(InputReader in, PrintWriter out) {

		int N = in.nextInt();
		long[] tab = new long[N];
		for (int i = 0; i < N; i++) {
			long ri = in.nextLong();
			long hi = in.nextLong();
			tab[i] = ri * ri * hi;
		}

		int[] M = new int[N + 1];
		long[] partResult = new long[N + 1];

		M[0] = 0;
		M[1] = 0;
		partResult[1] = tab[0];
		int longest = 1;

		for (int i = 1; i < N; i++) {
			long curr = tab[i];
			int index = binarySearch(M, tab, curr, 1, longest);

			if(tab[M[index]] < curr) {
				if(index != longest) {
					while(true);
				}
				partResult[index + 1] = partResult[index] + curr;
				M[index + 1] = i;
				longest++;
			} else if (index > 0 && partResult[index] < partResult[index - 1] + curr ) {
				partResult[index] = partResult[index -1 ] + curr;
				M[index] = i;
			}
		}

		long res = 0;
		for (int i = 0; i < partResult.length; i++) {
			res = Math.max(res, partResult[i]);
		}
		out.println(res * Math.PI);
	}

	private static int binarySearch(int[] M, long[] tab, long curr, int left, int right) {

		if (left == right) {
			return left;
		}
		int middle = left + (right - left) / 2;

		if (tab[M[middle]] < curr) {
			left = middle + 1;
		} else {
			right = middle;
		}

		return binarySearch(M, tab, curr, left, right);
	}

	/*
	 *
	 */
	// --------------------------------------------------------
	static class InputReader {
		public BufferedReader reader;
		public StringTokenizer tokenizer;

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

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

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

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

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

		public String nextLine() {
			String str = "";
			try {
				str = reader.readLine();
			} catch (IOException e) {
				e.printStackTrace();
			}

			return str;
		}
	}
}


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

public class Main {

	static class Pair implements Comparable<Pair> {

		long volume;
		long sum;

		public Pair(long volume, long sum) {
			this.volume = volume;
			this.sum = sum;
		}

		@Override
		public int compareTo(Pair other) {
			int compareVolume = Long.compare(volume, other.volume);
			int compareSum = Long.compare(sum, other.sum);
			if (compareVolume != 0) {
				return compareVolume;
			} else {
				return compareSum;
			}
		}
	}

	public static void main(String[] args) {

		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		solve(in, out);
		out.close();
	}

	private static void solve(InputReader in, PrintWriter out) {

		int N = in.nextInt();
		Pair[] arr = new Pair[N];
		for (int i = 0; i < N; i++) {
			long ri = in.nextLong();
			long hi = in.nextLong();
			arr[i] = new Pair(ri * ri * hi, 0);
		}

		TreeSet<Pair> treeSet = new TreeSet<Pair>();
		long res = 0;

		for (int i = 0; i < N; i++) {
			Pair curr = arr[i];

			Pair floorBound = treeSet.floor(curr);
			if (floorBound != null) {
				curr.sum = curr.volume + floorBound.sum;
			} else {
				curr.sum = curr.volume;
			}

			while (true) {
				Pair toDelete = treeSet.ceiling(curr);
				if (toDelete == null || toDelete.sum > curr.sum) {
					break;
				} else {
					treeSet.remove(toDelete);
				}
			}
			treeSet.add(curr);
			res = Math.max(res, curr.sum);
		}

		out.println(res * Math.PI);
	}

	/*
	 *
	 */
	// --------------------------------------------------------
	static class InputReader {
		public BufferedReader reader;
		public StringTokenizer tokenizer;

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

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

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

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

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

		public String nextLine() {
			String str = "";
			try {
				str = reader.readLine();
			} catch (IOException e) {
				e.printStackTrace();
			}

			return str;
		}
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {

	public static void main(String[] args) {

		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		solve(in, out);
		out.close();
	}

	static class Pair implements Comparable<Pair> {

		int num;
		long volume;

		public Pair(int num, long volume) {
			this.num = num;
			this.volume = volume;
		}

		@Override
		public int compareTo(Pair other) {
			return Long.compare(volume, other.volume);
		}
	}

	private static void solve(InputReader in, PrintWriter out) {

		int M = 131072;
		int N = in.nextInt();
		long[] tab = new long[N];
		Pair[] cakes = new Pair[N];

		for (int i = 0; i < N; i++) {
			long ri = in.nextLong();
			long hi = in.nextLong();
			tab[i] = ri * ri * hi;
			cakes[i] = new Pair(i + 1, ri * ri * hi);
		}
		Arrays.sort(cakes);

		long[] segmentTree = new long[2 * M];
		for (Pair curr : cakes) {
			long bestPred = findFromInterval(segmentTree, M, 1, curr.num - 1);
			long value = Math.max(bestPred, 0) + curr.volume;
			insertValueIntoPosition(segmentTree, M, value, curr.num);
		}

		out.println(segmentTree[1] * Math.PI);
	}

	private static void insertValueIntoPosition(long[] segmentTree, int M, long value, int num) {

		int index = M + num;
		segmentTree[index] = value;

		while (index >= 1) {
			segmentTree[index] = Math.max(segmentTree[index], value);
			index /= 2;
		}
	}

	private static long findFromInterval(long[] segmentTree, int M, int left, int right) {
		if (left > right) {
			return -1;
		}

		long max = Math.max(segmentTree[M + left], segmentTree[M + right]);
		while (left / 2 != right / 2) {
			int parentLeft = left / 2;
			int parentRight = right / 2;
			if (parentLeft * 2 == left) {
				// this is left son
				max = Math.max(max, segmentTree[parentLeft * 2 + 1]);
			}

			if (parentRight * 2 + 1 == right) {
				// this is right son
				max = Math.max(max, segmentTree[parentRight * 2]);
			}

			left /= 2;
			right /= 2;
		}
		return max;
	}

	/*
	 *
	 */
	// --------------------------------------------------------
	static class InputReader {
		public BufferedReader reader;
		public StringTokenizer tokenizer;

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

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

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

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

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

		public String nextLine() {
			String str = "";
			try {
				str = reader.readLine();
			} catch (IOException e) {
				e.printStackTrace();
			}

			return str;
		}
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {

	public static void main(String[] args) {

		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		solve(in, out);
		out.close();
	}

	static class Pair implements Comparable<Pair> {

		int num;
		long volume;

		public Pair(int num, long volume) {
			this.num = num;
			this.volume = volume;
		}

		@Override
		public int compareTo(Pair other) {

			int compareVolume = Long.compare(volume, other.volume);
			if (compareVolume != 0) {
				return compareVolume;
			} else {
				return Integer.compare(other.num, num);
			}
		}
	}

	private static void solve(InputReader in, PrintWriter out) {

		int M = 131072;
		int N = in.nextInt();
		long[] tab = new long[N];
		Pair[] cakes = new Pair[N];

		for (int i = 0; i < N; i++) {
			long ri = in.nextLong();
			long hi = in.nextLong();
			tab[i] = ri * ri * hi;
			cakes[i] = new Pair(i + 1, ri * ri * hi);
		}
		Arrays.sort(cakes);

		long[] segmentTree = new long[2 * M];
		for (Pair curr : cakes) {
			long bestPred = findFromInterval(segmentTree, M, 1, curr.num - 1);
			long value = Math.max(bestPred, 0) + curr.volume;
			insertValueIntoPosition(segmentTree, M, value, curr.num);
		}

		out.println(segmentTree[1] * Math.PI);
	}

	private static void insertValueIntoPosition(long[] segmentTree, int M, long value, int num) {

		int index = M + num;
		segmentTree[index] = value;

		while (index >= 1) {
			segmentTree[index] = Math.max(segmentTree[index], value);
			index /= 2;
		}
	}

	private static long findFromInterval(long[] segmentTree, int M, int left, int right) {
		left += M;
		right += M;
		if (left > right) {
			return -1;
		}

		long max = Math.max(segmentTree[left], segmentTree[right]);
		while (left / 2 != right / 2) {
			int parentLeft = left / 2;
			int parentRight = right / 2;
			if (parentLeft * 2 == left) {
				// this is left son
				max = Math.max(max, segmentTree[parentLeft * 2 + 1]);
			}

			if (parentRight * 2 + 1 == right) {
				// this is right son
				max = Math.max(max, segmentTree[parentRight * 2]);
			}

			left /= 2;
			right /= 2;
		}
		return max;
	}

	/*
	 *
	 */
	// --------------------------------------------------------
	static class InputReader {
		public BufferedReader reader;
		public StringTokenizer tokenizer;

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

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

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

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

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

		public String nextLine() {
			String str = "";
			try {
				str = reader.readLine();
			} catch (IOException e) {
				e.printStackTrace();
			}

			return str;
		}
	}
}


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

public class Main {

	static class Pair implements Comparable<Pair> {

		long volume;
		long sum;

		public Pair(long volume, long sum) {
			this.volume = volume;
			this.sum = sum;
		}

		@Override
		public int compareTo(Pair other) {
			int compareVolume = Long.compare(volume, other.volume);
			int compareSum = Long.compare(sum, other.sum);
			if (compareVolume != 0) {
				return compareVolume;
			} else {
				return compareSum;
			}
		}
	}

	public static void main(String[] args) {

		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		solve(in, out);
		out.close();
	}

	private static void solve(InputReader in, PrintWriter out) {

		int N = in.nextInt();
		Pair[] arr = new Pair[N];
		for (int i = 0; i < N; i++) {
			long ri = in.nextLong();
			long hi = in.nextLong();
			arr[i] = new Pair(ri * ri * hi, ri * ri * hi);
		}

		TreeSet<Pair> treeSet = new TreeSet<Pair>();
		long res = 0;

		for (int i = 0; i < N; i++) {
			Pair curr = arr[i];

			Pair floorBound = treeSet.floor(curr);
			if (floorBound != null) {
				curr.sum += floorBound.sum;
			}

			while (true) {
				Pair toDelete = treeSet.ceiling(curr);
				if (toDelete == null) {
					break;
				} else {
					treeSet.remove(toDelete);
				}
			}
			treeSet.add(curr);
			res = Math.max(res, curr.sum);
		}

		out.println(res * Math.PI);
	}

	/*
	 *
	 */
	// --------------------------------------------------------
	static class InputReader {
		public BufferedReader reader;
		public StringTokenizer tokenizer;

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

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

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

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

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

		public String nextLine() {
			String str = "";
			try {
				str = reader.readLine();
			} catch (IOException e) {
				e.printStackTrace();
			}

			return str;
		}
	}
}


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

public class Main {

	static class Pair implements Comparable<Pair> {

		long volume;
		long sum;

		public Pair(long volume, long sum) {
			this.volume = volume;
			this.sum = sum;
		}

		@Override
		public int compareTo(Pair other) {
			int compareVolume = Long.compare(volume, other.volume);
			int compareSum = Long.compare(sum, other.sum);
			if (compareVolume != 0) {
				return compareVolume;
			} else {
				return compareSum;
			}
		}
	}

	public static void main(String[] args) {

		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		solve(in, out);
		out.close();
	}

	private static void solve(InputReader in, PrintWriter out) {

		int N = in.nextInt();
		Pair[] arr = new Pair[N];
		for (int i = 0; i < N; i++) {
			long ri = in.nextLong();
			long hi = in.nextLong();
			arr[i] = new Pair(ri * ri * hi, ri * ri * hi);
		}

		TreeSet<Pair> treeSet = new TreeSet<Pair>();
		long res = 0;

		for (int i = 0; i < N; i++) {
			Pair curr = arr[i];

			Pair floorBound = treeSet.floor(curr);
			if (floorBound != null) {
				curr.sum += floorBound.sum;
				if(curr.volume == floorBound.volume) {
					treeSet.remove(floorBound);
				}
			}

			while (true) {
				Pair toDelete = treeSet.ceiling(curr);
				if (toDelete == null || toDelete.sum > curr.sum) {
					break;
				} else {
					treeSet.remove(toDelete);
				}
			}
			treeSet.add(curr);
			res = Math.max(res, curr.sum);
		}

		out.println(res * Math.PI);
	}

	/*
	 *
	 */
	// --------------------------------------------------------
	static class InputReader {
		public BufferedReader reader;
		public StringTokenizer tokenizer;

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

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

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

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

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

		public String nextLine() {
			String str = "";
			try {
				str = reader.readLine();
			} catch (IOException e) {
				e.printStackTrace();
			}

			return str;
		}
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {

	public static void main(String[] args) {

		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		solve(in, out);
		out.close();
	}

	static class Pair implements Comparable<Pair> {

		int num;
		long volume;

		public Pair(int num, long volume) {
			this.num = num;
			this.volume = volume;
		}

		@Override
		public int compareTo(Pair other) {

			int compareVolume = Long.compare(volume, other.volume);
			if (compareVolume != 0) {
				return compareVolume;
			} else {
				return Integer.compare(other.num, num);
			}
		}
	}

	private static void solve(InputReader in, PrintWriter out) {

		int M = 131072;
		int N = in.nextInt();
		long[] tab = new long[N];
		Pair[] cakes = new Pair[N];

		for (int i = 0; i < N; i++) {
			long ri = in.nextLong();
			long hi = in.nextLong();
			tab[i] = ri * ri * hi;
			cakes[i] = new Pair(i + 1, ri * ri * hi);
		}
		Arrays.sort(cakes);

		long[] segmentTree = new long[2 * M];
		for (Pair curr : cakes) {
			long bestPred = findFromInterval(segmentTree, M, 1, curr.num - 1);
			long value = Math.max(bestPred, 0) + curr.volume;
			insertValueIntoPosition(segmentTree, M, value, curr.num);
		}

		out.println(segmentTree[1] * Math.PI);
	}

	private static void insertValueIntoPosition(long[] segmentTree, int M, long value, int num) {

		int index = M + num;
		segmentTree[index] = value;

		while (index >= 1) {
			segmentTree[index] = Math.max(segmentTree[index], value);
			index /= 2;
		}
	}

	private static long findFromInterval(long[] segmentTree, int M, int left, int right) {
		if (left > right) {
			return -1;
		}

		long max = Math.max(segmentTree[M + left], segmentTree[M + right]);
		while (left / 2 != right / 2) {
			int parentLeft = left / 2;
			int parentRight = right / 2;
			if (parentLeft * 2 == left) {
				// this is left son
				max = Math.max(max, segmentTree[parentLeft * 2 + 1]);
			}

			if (parentRight * 2 + 1 == right) {
				// this is right son
				max = Math.max(max, segmentTree[parentRight * 2]);
			}

			left /= 2;
			right /= 2;
		}
		return max;
	}

	/*
	 *
	 */
	// --------------------------------------------------------
	static class InputReader {
		public BufferedReader reader;
		public StringTokenizer tokenizer;

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

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

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

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

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

		public String nextLine() {
			String str = "";
			try {
				str = reader.readLine();
			} catch (IOException e) {
				e.printStackTrace();
			}

			return str;
		}
	}
}


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

public class Main {

	public static void main(String[] args) {

		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		solve(in, out);
		out.close();
	}

	private static void solve(InputReader in, PrintWriter out) {

		int N = in.nextInt();
		long[] tab = new long[N];
		for (int i = 0; i < N; i++) {
			long ri = in.nextLong();
			long hi = in.nextLong();
			tab[i] = ri * ri * hi;
		}

		int[] M = new int[N + 1];
		long[] partResult = new long[N + 1];

		M[0] = 0;
		M[1] = 0;
		partResult[1] = tab[0];
		int longest = 1;

		for (int i = 1; i < N; i++) {
			long curr = tab[i];
			int index = binarySearch(M, tab, curr, 1, longest);

			if(tab[M[index]] < curr) {
				if(index != longest) {
					while(true) {

					}
				}
				partResult[index + 1] = partResult[index] + curr;
				M[index + 1] = i;
				longest++;
			} else if (index > 0 && partResult[index] < partResult[index - 1] + curr ) {
				partResult[index] = partResult[index -1 ] + curr;
				M[index] = i;
			}
		}

		long res = 0;
		for (int i = 0; i < partResult.length; i++) {
			res = Math.max(res, partResult[i]);
		}
		out.println(res * Math.PI);
	}

	private static int binarySearch(int[] M, long[] tab, long curr, int left, int right) {

		if (left == right) {
			return left;
		}
		int middle = left + (right - left) / 2;

		if (tab[M[middle]] < curr) {
			left = middle + 1;
		} else {
			right = middle;
		}

		return binarySearch(M, tab, curr, left, right);
	}

	/*
	 *
	 */
	// --------------------------------------------------------
	static class InputReader {
		public BufferedReader reader;
		public StringTokenizer tokenizer;

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

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

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

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

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

		public String nextLine() {
			String str = "";
			try {
				str = reader.readLine();
			} catch (IOException e) {
				e.printStackTrace();
			}

			return str;
		}
	}
}


import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.util.Arrays;
import java.util.StringTokenizer;

public class Main {

	public static void main(String[] args) {

		InputStream inputStream = System.in;
		OutputStream outputStream = System.out;
		InputReader in = new InputReader(inputStream);
		PrintWriter out = new PrintWriter(outputStream);
		solve(in, out);
		out.close();
	}

	static class Pair implements Comparable<Pair> {

		int num;
		long volume;

		public Pair(int num, long volume) {
			this.num = num;
			this.volume = volume;
		}

		@Override
		public int compareTo(Pair other) {

			int compareVolume = Long.compare(volume, other.volume);
			if (compareVolume != 0) {
				return compareVolume;
			} else {
				return -Integer.compare(num, other.num);
			}
		}
	}

	private static void solve(InputReader in, PrintWriter out) {

		int M = 131072;
		int N = in.nextInt();
		long[] tab = new long[N];
		Pair[] cakes = new Pair[N];

		for (int i = 0; i < N; i++) {
			long ri = in.nextLong();
			long hi = in.nextLong();
			tab[i] = ri * ri * hi;
			cakes[i] = new Pair(i + 1, ri * ri * hi);
		}
		Arrays.sort(cakes);

		long[] segmentTree = new long[2 * M];
		for (Pair curr : cakes) {
			long bestPred = findFromInterval(segmentTree, M, 1, curr.num - 1);
			long value = Math.max(bestPred, 0) + curr.volume;
			insertValueIntoPosition(segmentTree, M, value, curr.num);
		}

		out.println(segmentTree[1] * Math.PI);
	}

	private static void insertValueIntoPosition(long[] segmentTree, int M, long value, int num) {

		int index = M + num;
		segmentTree[index] = value;

		while (index >= 1) {
			segmentTree[index] = Math.max(segmentTree[index], value);
			index /= 2;
		}
	}

	private static long findFromInterval(long[] segmentTree, int M, int left, int right) {
		if (left > right) {
			return -1;
		}

		long max = Math.max(segmentTree[M + left], segmentTree[M + right]);
		while (left / 2 != right / 2) {
			int parentLeft = left / 2;
			int parentRight = right / 2;
			if (parentLeft * 2 == left) {
				// this is left son
				max = Math.max(max, segmentTree[parentLeft * 2 + 1]);
			}

			if (parentRight * 2 + 1 == right) {
				// this is right son
				max = Math.max(max, segmentTree[parentRight * 2]);
			}

			left /= 2;
			right /= 2;
		}
		return max;
	}

	/*
	 *
	 */
	// --------------------------------------------------------
	static class InputReader {
		public BufferedReader reader;
		public StringTokenizer tokenizer;

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

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

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

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

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

		public String nextLine() {
			String str = "";
			try {
				str = reader.readLine();
			} catch (IOException e) {
				e.printStackTrace();
			}

			return str;
		}
	}
}


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

public class p629d {
    public static class Cake implements Comparable<Cake> {
        public final int i;
        public final int v;
        public Cake(int i, int v) {
            this.i = i;
            this.v = v;
        }
        public int compareTo(Cake other) {
            int c = Integer.compare(this.v, other.v);
            if (c == 0) {
                c = Integer.compare(this.i, other.i);
            }
            return c;
        }
        public int hashCode() {
            return this.i;
        }
        public boolean equals(Object other) {
            if (other == null || ! (other instanceof Cake)) {
                return false;
            }
            Cake cother = (Cake) other;
            return this.i == cother.i;
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));
        Scanner lscan = new Scanner(cin.readLine());
        int n = lscan.nextInt();
        lscan.close();
        List<Cake> cakes = new ArrayList<>(n);
        for (int i = 0; i < n; i++) {
            lscan = new Scanner(cin.readLine());
            int r = lscan.nextInt();
            int h = lscan.nextInt();
            lscan.close();
            cakes.add(new Cake(i, r*r*h));
        }
        System.out.println(Math.PI * maxStack(cakes));
    }

    public static int maxStack(List<Cake> cakes) {
        HashMap<Cake, Integer> stacks = new HashMap<>();
        TreeSet<Cake> cbv = new TreeSet<>();
        for (Cake cake : cakes) {
            Cake pcake = cbv.lower(cake);
            int sv = cake.v;
            if (pcake != null) {
                sv += stacks.get(pcake);;
            }
            stacks.put(cake, sv);
            for (Cake ncake : cbv.tailSet(cake)) {
                if (stacks.get(ncake) < sv) {
                    stacks.put(ncake, sv);
                } else {
                    break;
                }
            }
            cbv.add(cake);
        }
        return Collections.max(stacks.values());
    }

}


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

public class p629d {
    public static class Cake implements Comparable<Cake> {
        public final int i;
        public final int v;
        public Cake(int i, int v) {
            this.i = i;
            this.v = v;
        }
        public int compareTo(Cake other) {
            int c = Integer.compare(this.v, other.v);
            if (c == 0) {
                c = Integer.compare(this.i, other.i);
            }
            return c;
        }
        public int hashCode() {
            return this.i;
        }
        public boolean equals(Object other) {
            if (other == null || ! (other instanceof Cake)) {
                return false;
            }
            Cake cother = (Cake) other;
            return this.i == cother.i;
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));
        Scanner lscan = new Scanner(cin.readLine());
        int n = lscan.nextInt();
        lscan.close();
        List<Cake> cakes = new ArrayList<>(n);
        for (int i = 0; i < n; i++) {
            lscan = new Scanner(cin.readLine());
            int r = lscan.nextInt();
            int h = lscan.nextInt();
            lscan.close();
            cakes.add(new Cake(i, r*r*h));
        }
        System.out.println(Math.PI * maxStack(cakes));
    }

    public static int maxStack(List<Cake> cakes) {
        HashMap<Cake, Integer> stacks = new HashMap<>();
        TreeSet<Cake> cbv = new TreeSet<>();
        for (Cake cake : cakes) {
            Cake pcake = cbv.lower(cake);
            int sv = cake.v;
            if (pcake != null) {
                sv += stacks.get(pcake);;
            }
            stacks.put(cake, sv);
            List<Cake> toRemove = new ArrayList<>();
            for (Cake ncake : cbv.tailSet(cake)) {
                if (stacks.get(ncake) < sv) {
                    toRemove.add(ncake);
                } else {
                    break;
                }
            }
            for (Cake rcake : toRemove) {
                cbv.remove(rcake);
            }
            cbv.add(cake);
        }
        return Collections.max(stacks.values());
    }

}


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

public class p629d {
    public static class Cake implements Comparable<Cake> {
        public final int i;
        public final long v;
        public Cake(int i, long v) {
            this.i = i;
            this.v = v;
        }
        public int compareTo(Cake other) {
            int c = Long.compare(this.v, other.v);
            if (c == 0) {
                c = Integer.compare(this.i, other.i);
            }
            return c;
        }
        public int hashCode() {
            return this.i;
        }
        public boolean equals(Object other) {
            if (other == null || ! (other instanceof Cake)) {
                return false;
            }
            Cake cother = (Cake) other;
            return this.i == cother.i;
        }
        public String toString() {
            return "("+i+", "+v+")";
        }
    }

    public static void main(String[] args) throws IOException {
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        List<Cake> cakes = new ArrayList<>(n);
        for (int i = 0; i < n; i++) {
            int r = scan.nextInt();
            int h = scan.nextInt();
            cakes.add(new Cake(i, ((long)r)*((long)r)*((long)h)));
        }
        System.out.printf("%.6f%n", Math.PI * maxStack(cakes));
    }

    public static long maxStack(List<Cake> cakes) {
        HashMap<Cake, Long> stacks = new HashMap<>();
        TreeSet<Cake> cbv = new TreeSet<>();
        for (Cake cake : cakes) {
            // System.err.println("considering "+cake);

            List<Cake> toRemove = new ArrayList<>();

            Cake pcake = null;
            for (Cake ocake : cbv.headSet(cake, false).descendingSet()) {
                if (ocake.v == cake.v) {
                    // System.err.println("removing "+ocake);
                    toRemove.add(ocake);
                } else {
                    pcake = ocake;
                    break;
                }
            }
            // System.err.println("pcake="+pcake);

            long sv = cake.v;
            if (pcake != null) {
                sv += stacks.get(pcake);;
            }
            // System.err.println("stack="+sv);

            for (Cake ocake : cbv.tailSet(cake, false)) {
                if (stacks.get(ocake) < sv) {
                    // System.err.println("removing "+ocake);
                    toRemove.add(ocake);
                } else {
                    break;
                }
            }

            cbv.removeAll(toRemove);

            stacks.put(cake, sv);
            cbv.add(cake);

            // System.err.println("cbv="+cbv);
        }
        long max = Collections.max(stacks.values());
        // System.err.println("max="+max);
        return max;
    }

}


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

public class p629d {
    public static class Cake implements Comparable<Cake> {
        public final int i;
        public final int v;
        public Cake(int i, int v) {
            this.i = i;
            this.v = v;
        }
        public int compareTo(Cake other) {
            int c = Integer.compare(this.v, other.v);
            if (c == 0) {
                c = Integer.compare(this.i, other.i);
            }
            return c;
        }
        public int hashCode() {
            return this.i;
        }
        public boolean equals(Object other) {
            if (other == null || ! (other instanceof Cake)) {
                return false;
            }
            Cake cother = (Cake) other;
            return this.i == cother.i;
        }
        public String toString() {
            return "("+i+", "+v+")";
        }
    }

    public static void main(String[] args) throws IOException {
//         System.err.println("parsing");
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        List<Cake> cakes = new ArrayList<>(n);
        for (int i = 0; i < n; i++) {
            int r = scan.nextInt();
            int h = scan.nextInt();
            cakes.add(new Cake(i, r*r*h));
        }
        System.out.println(Math.PI * maxStack(cakes));
    }

    public static int maxStack(List<Cake> cakes) {
        HashMap<Cake, Integer> stacks = new HashMap<>();
        TreeSet<Cake> cbv = new TreeSet<>();
        for (Cake cake : cakes) {
//             System.err.println("considering "+cake);

            List<Cake> toRemove = new ArrayList<>();

            Cake pcake = null;
            for (Cake ocake : cbv.headSet(cake, false).descendingSet()) {
                if (ocake.v == cake.v) {
//                     System.err.println("removing "+ocake);
                    toRemove.add(ocake);
                } else {
                    pcake = ocake;
                    break;
                }
            }
//             System.err.println("pcake="+pcake);

            int sv = cake.v;
            if (pcake != null) {
                sv += stacks.get(pcake);;
            }
//             System.err.println("stack="+sv);

            for (Cake ocake : cbv.tailSet(cake, false)) {
                if (stacks.get(ocake) < sv) {
//                     System.err.println("removing "+ocake);
                    toRemove.add(ocake);
                } else {
                    break;
                }
            }

            cbv.removeAll(toRemove);

            stacks.put(cake, sv);
            cbv.add(cake);

//             System.err.println("cbv="+cbv);
        }
        return Collections.max(stacks.values());
    }

}


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

public class p629d {
    public static class Cake implements Comparable<Cake> {
        public final int i;
        public final int v;
        public Cake(int i, int v) {
            this.i = i;
            this.v = v;
        }
        public int compareTo(Cake other) {
            int c = Integer.compare(this.v, other.v);
            if (c == 0) {
                c = Integer.compare(this.i, other.i);
            }
            return c;
        }
        public int hashCode() {
            return this.i;
        }
        public boolean equals(Object other) {
            if (other == null || ! (other instanceof Cake)) {
                return false;
            }
            Cake cother = (Cake) other;
            return this.i == cother.i;
        }
    }

    public static void main(String[] args) throws IOException {
        BufferedReader cin = new BufferedReader(new InputStreamReader(System.in));
        Scanner lscan = new Scanner(cin.readLine());
        int n = lscan.nextInt();
        lscan.close();
        List<Cake> cakes = new ArrayList<>(n);
        for (int i = 0; i < n; i++) {
            lscan = new Scanner(cin.readLine());
            int r = lscan.nextInt();
            int h = lscan.nextInt();
            lscan.close();
            cakes.add(new Cake(i, r*r*h));
        }
        System.out.println(Math.PI * maxStack(cakes));
    }

    public static int maxStack(List<Cake> cakes) {
        HashMap<Cake, Integer> stacks = new HashMap<>();
        TreeSet<Cake> cbv = new TreeSet<>();
        for (Cake cake : cakes) {
            Cake pcake = cbv.lower(cake);
            int sv = cake.v;
            if (pcake != null) {
                sv += stacks.get(pcake);;
            }

            List<Cake> toRemove = new ArrayList<>();
            for (Cake ncake : cbv.tailSet(cake)) {
                if (stacks.get(ncake) < sv) {
                    toRemove.add(ncake);
                } else {
                    break;
                }
            }
            cbv.removeAll(toRemove);

            stacks.put(cake, sv);
            cbv.add(cake);
        }
        return Collections.max(stacks.values());
    }

}


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

public class p629d {
    public static class Cake implements Comparable<Cake> {
        public final int i;
        public final int v;
        public Cake(int i, int v) {
            this.i = i;
            this.v = v;
        }
        public int compareTo(Cake other) {
            int c = Integer.compare(this.v, other.v);
            if (c == 0) {
                c = Integer.compare(this.i, other.i);
            }
            return c;
        }
        public int hashCode() {
            return this.i;
        }
        public boolean equals(Object other) {
            if (other == null || ! (other instanceof Cake)) {
                return false;
            }
            Cake cother = (Cake) other;
            return this.i == cother.i;
        }
        public String toString() {
            return "("+i+", "+v+")";
        }
    }

    public static void main(String[] args) throws IOException {
//         System.out.println("parsing");
        Scanner scan = new Scanner(System.in);
        int n = scan.nextInt();
        List<Cake> cakes = new ArrayList<>(n);
        for (int i = 0; i < n; i++) {
            int r = scan.nextInt();
            int h = scan.nextInt();
            cakes.add(new Cake(i, r*r*h));
        }
        System.out.println(Math.PI * maxStack(cakes));
    }

    public static int maxStack(List<Cake> cakes) {
        HashMap<Cake, Integer> stacks = new HashMap<>();
        TreeSet<Cake> cbv = new TreeSet<>();
        for (Cake cake : cakes) {
//             System.out.println("considering "+cake);

            List<Cake> toRemove = new ArrayList<>();

            Cake pcake = null;
            for (Cake ocake : cbv.headSet(cake)) {
                if (ocake.v == cake.v) {
//                     System.out.println("removing "+ocake);
                    toRemove.add(ocake);
                } else {
                    pcake = ocake;
                    break;
                }
            }
//             System.out.println("pcake="+pcake);

            int sv = cake.v;
            if (pcake != null) {
                sv += stacks.get(pcake);;
            }
//             System.out.println("stack="+sv);

            for (Cake ocake : cbv.tailSet(cake)) {
                if (stacks.get(ocake) < sv) {
//                     System.out.println("removing "+ocake);
                    toRemove.add(ocake);
                } else {
                    break;
                }
            }

            cbv.removeAll(toRemove);

            stacks.put(cake, sv);
            cbv.add(cake);
        }
        return Collections.max(stacks.values());
    }

}


import java.io.*;
import java.util.*;
public final class birthday_cake
{
    static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	static FastScanner sc=new FastScanner(br);
    static PrintWriter out=new PrintWriter(System.out);
	static double pi=3.141592653589793238,tree[];
	static int max_val=0;

	static double get(int node,int s,int e,int l,int r)
	{
		if(s>e || l>e || r<s)
		{
			return 0;
		}
		if(l<=s && r>=e)
		{
			return tree[node];
		}
		else
		{
			int mid=(s+e)>>1;
			double q1=get(node<<1,s,mid,l,r),q2=get(node<<1|1,mid+1,e,l,r);
			return Math.max(q1,q2);
		}
	}

	static void update(int node,int s,int e,int l,int r,double val)
	{
		if(s>e || l>e || r<s)
		{
			return;
		}
		if(l<=s && r>=e)
		{
			tree[node]=Math.max(tree[node],val);
		}
		else
		{
			int mid=(s+e)>>1;
			update(node<<1,s,mid,l,r,val);update(node<<1|1,mid+1,e,l,r,val);
			tree[node]=Math.max(tree[node<<1],tree[node<<1|1]);
		}
	}

	public static void main(String args[]) throws Exception
	{
		int n=sc.nextInt();double[] a=new double[n],b=new double[n];int[] c=new int[n];
		for(int i=0;i<n;i++)
		{
			double r=sc.nextDouble(),h=sc.nextDouble(),vol=pi*r*r*h;
			a[i]=vol;b[i]=a[i];
		}
		Arrays.sort(b);
		for(int i=0;i<n;i++)
		{
			double temp=a[i];
			c[i]=Arrays.binarySearch(b,a[i])+1;
			max_val=Math.max(max_val,c[i]);
		}
		tree=new double[4*max_val];double res=0;
		for(int i=0;i<n;i++)
		{
			double max=get(1,0,max_val,1,c[i]-1);max+=a[i];
			res=Math.max(res,max);update(1,0,max_val,c[i],c[i],max);
		}
		out.printf("%.12f\n",res);
		out.close();
	}
}
class FastScanner
{
    BufferedReader in;
    StringTokenizer st;

    public FastScanner(BufferedReader in) {
        this.in = in;
    }

    public String nextToken() throws Exception {
        while (st == null || !st.hasMoreTokens()) {
            st = new StringTokenizer(in.readLine());
        }
        return st.nextToken();
    }

	public String next() throws Exception {
		return nextToken().toString();
	}

    public int nextInt() throws Exception {
        return Integer.parseInt(nextToken());
    }

    public long nextLong() throws Exception {
        return Long.parseLong(nextToken());
    }

    public double nextDouble() throws Exception {
        return Double.parseDouble(nextToken());
    }
}


import java.io.*;
import java.util.*;
public final class birthday_cake
{
    static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	static FastScanner sc=new FastScanner(br);
    static PrintWriter out=new PrintWriter(System.out);
	static double pi=3.141592653589793238,tree[];
	static int max_val=0;

	static double get(int node,int s,int e,int l,int r)
	{
		if(s>e || l>e || r<s)
		{
			return 0;
		}
		if(l<=s && r>=e)
		{
			return tree[node];
		}
		else
		{
			int mid=(s+e)>>1;
			double q1=get(node<<1,s,mid,l,r),q2=get(node<<1|1,mid+1,e,l,r);
			return Math.max(q1,q2);
		}
	}

	static void update(int node,int s,int e,int l,int r,double val)
	{
		if(s>e || l>e || r<s)
		{
			return;
		}
		if(l<=s && r>=e)
		{
			tree[node]=Math.max(tree[node],val);
		}
		else
		{
			int mid=(s+e)>>1;
			update(node<<1,s,mid,l,r,val);update(node<<1|1,mid+1,e,l,r,val);
			tree[node]=Math.max(tree[node<<1],tree[node<<1|1]);
		}
	}

	public static void main(String args[]) throws Exception
	{
		int n=sc.nextInt();double[] a=new double[n],b=new double[n];int[] c=new int[n];
		for(int i=0;i<n;i++)
		{
			double r=sc.nextDouble(),h=sc.nextDouble(),vol=r*r*h;
			a[i]=vol;b[i]=a[i];
		}
		Arrays.sort(b);
		for(int i=0;i<n;i++)
		{
			double temp=a[i];
			c[i]=Arrays.binarySearch(b,a[i])+1;
			max_val=Math.max(max_val,c[i]);
		}
		tree=new double[4*max_val];double res=0;
		for(int i=0;i<n;i++)
		{
			double max=0;
			if(c[i]!=1)
			{
				max=get(1,0,max_val,1,c[i]-1);
			}
			max+=a[i];
			res=Math.max(res,max);update(1,0,max_val,c[i],c[i],max);
		}
		res=res*pi;out.printf("%.12f\n",res);
		out.close();
	}
}
class FastScanner
{
    BufferedReader in;
    StringTokenizer st;

    public FastScanner(BufferedReader in) {
        this.in = in;
    }

    public String nextToken() throws Exception {
        while (st == null || !st.hasMoreTokens()) {
            st = new StringTokenizer(in.readLine());
        }
        return st.nextToken();
    }

	public String next() throws Exception {
		return nextToken().toString();
	}

    public int nextInt() throws Exception {
        return Integer.parseInt(nextToken());
    }

    public long nextLong() throws Exception {
        return Long.parseLong(nextToken());
    }

    public double nextDouble() throws Exception {
        return Double.parseDouble(nextToken());
    }
}


import java.io.*;
import java.util.*;
public final class birthday_cake
{
    static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	static FastScanner sc=new FastScanner(br);
    static PrintWriter out=new PrintWriter(System.out);
	static double pi=3.14159265359,tree[];
	static int max_val=0;

	static double get(int node,int s,int e,int l,int r)
	{
		if(s>e || l>e || r<s)
		{
			return -1;
		}
		if(l<=s && r>=e)
		{
			return tree[node];
		}
		else
		{
			int mid=(s+e)>>1;
			double q1=get(node<<1,s,mid,l,r),q2=get(node<<1|1,mid+1,e,l,r);
			return Math.max(q1,q2);
		}
	}

	static void update(int node,int s,int e,int l,int r,double val)
	{
		if(s>e || l>e || r<s)
		{
			return;
		}
		if(l<=s && r>=e)
		{
			tree[node]=Math.max(tree[node],val);
		}
		else
		{
			int mid=(s+e)>>1;
			update(node<<1,s,mid,l,r,val);update(node<<1|1,mid+1,e,l,r,val);
			tree[node]=Math.max(tree[node<<1],tree[node<<1|1]);
		}
	}

	public static void main(String args[]) throws Exception
	{
		int n=sc.nextInt();double[] a=new double[n],b=new double[n];int[] c=new int[n];
		for(int i=0;i<n;i++)
		{
			double r=sc.nextDouble(),h=sc.nextDouble(),vol=pi*r*r*h;
			a[i]=vol;b[i]=a[i];
		}
		Arrays.sort(b);
		for(int i=0;i<n;i++)
		{
			double temp=a[i];
			c[i]=Arrays.binarySearch(b,a[i])+1;
			max_val=Math.max(max_val,c[i]);
		}
		tree=new double[4*max_val];double res=0;
		for(int i=0;i<n;i++)
		{
			double max=0;
			if(c[i]!=1)
			{
				max=get(1,0,max_val,1,c[i]-1);
			}
			max+=a[i];
			res=Math.max(res,max);
			update(1,0,max_val,c[i],c[i],max);
		}
		out.println(res);
		out.close();
	}
}
class FastScanner
{
    BufferedReader in;
    StringTokenizer st;

    public FastScanner(BufferedReader in) {
        this.in = in;
    }

    public String nextToken() throws Exception {
        while (st == null || !st.hasMoreTokens()) {
            st = new StringTokenizer(in.readLine());
        }
        return st.nextToken();
    }

	public String next() throws Exception {
		return nextToken().toString();
	}

    public int nextInt() throws Exception {
        return Integer.parseInt(nextToken());
    }

    public long nextLong() throws Exception {
        return Long.parseLong(nextToken());
    }

    public double nextDouble() throws Exception {
        return Double.parseDouble(nextToken());
    }
}


import java.io.*;
import java.util.*;
public final class birthday_cake
{
    static BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
	static FastScanner sc=new FastScanner(br);
    static PrintWriter out=new PrintWriter(System.out);
	static double pi=3.14159265359,tree[];
	static int max_val=0;

	static double get(int node,int s,int e,int l,int r)
	{
		if(s>e || l>e || r<s)
		{
			return -1;
		}
		if(l<=s && r>=e)
		{
			return tree[node];
		}
		else
		{
			int mid=(s+e)>>1;
			double q1=get(node<<1,s,mid,l,r),q2=get(node<<1|1,mid+1,e,l,r);
			return Math.max(q1,q2);
		}
	}

	static void update(int node,int s,int e,int l,int r,double val)
	{
		if(s>e || l>e || r<s)
		{
			return;
		}
		if(l<=s && r>=e)
		{
			tree[node]=Math.max(tree[node],val);
		}
		else
		{
			int mid=(s+e)>>1;
			update(node<<1,s,mid,l,r,val);update(node<<1|1,mid+1,e,l,r,val);
			tree[node]=Math.max(tree[node<<1],tree[node<<1|1]);
		}
	}

	public static void main(String args[]) throws Exception
	{
		int n=sc.nextInt();double[] a=new double[n],b=new double[n];int[] c=new int[n];
		for(int i=0;i<n;i++)
		{
			double r=sc.nextDouble(),h=sc.nextDouble(),vol=pi*r*r*h;
			a[i]=vol;b[i]=a[i];
		}
		Arrays.sort(b);
		for(int i=0;i<n;i++)
		{
			double temp=a[i];
			c[i]=Arrays.binarySearch(b,a[i])+1;
			max_val=Math.max(max_val,c[i]);
		}
		tree=new double[4*max_val];double res=0;
		for(int i=0;i<n;i++)
		{
			double max=0;
			if(c[i]!=1)
			{
				max=get(1,0,max_val,1,c[i]-1);
			}
			max+=a[i];
			res=Math.max(res,max);
			update(1,0,max_val,c[i],c[i],max);
		}
		out.printf("%.12f\n",res);
		out.close();
	}
}
class FastScanner
{
    BufferedReader in;
    StringTokenizer st;

    public FastScanner(BufferedReader in) {
        this.in = in;
    }

    public String nextToken() throws Exception {
        while (st == null || !st.hasMoreTokens()) {
            st = new StringTokenizer(in.readLine());
        }
        return st.nextToken();
    }

	public String next() throws Exception {
		return nextToken().toString();
	}

    public int nextInt() throws Exception {
        return Integer.parseInt(nextToken());
    }

    public long nextLong() throws Exception {
        return Long.parseLong(nextToken());
    }

    public double nextDouble() throws Exception {
        return Double.parseDouble(nextToken());
    }
}


#include<iostream>
#include<string>
#include<set>
using namespace std;
void main(){
	set<pair<string,string>>Indian_Summer;
	int n;
	string a,b;
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a>>b;
		Indian_Summer.insert(pair<string,string>(a,b));
	}
	cout<<Indian_Summer.size()<<endl;
}


//44A Winter Computer School Contest #2

#include<iostream>
#include<stdio.h>
#include<string>
#include<conio.h>
using namespace std;
string a[101][3],b[101][3];
void main()
{
	int n;
	cin>>n;
	for(int i=1;i<=n;i++)
		for(int j=1;j<=2;j++)
			cin>>a[i][j];
	int k=2;
	b[1][1]=a[1][1];
	b[1][2]=a[1][2];
	for(int i=2;i<=n;i++)
	{
		int flag=0;
		for(int j=1;j<k;j++)
		{
			if(b[j][1]==a[i][1] && b[j][2]==a[i][2])
			{
				flag=1;
				break;
			}
		}
		if(flag==0)
		{
			b[k][1]=a[i][1];
			b[k][2]=a[i][2];
			k++;
		}
	}
	cout<<k-1<<endl;
}


#include <iostream>
#include <cstring>
#include <string.h>
using namespace std;

struct struc
{
    char name[11];
    char color[11];
};

int main()
{
    int n, count = 0;
    cin >> n;
    struc* a = new struc[n];
    int* rez = new int[n];
    for ( int j = 0; j < n; ++j )
    {
        cin >> a[j].name >> a[j].color;
        rez[j] = 0;
    }
    for ( int j = 0; j < n - 1; ++j )
        for ( int i = j + 1; i < n; ++i )
        {
            if ( rez[j] != 1 )
            {
                rez[j] = 1;
                ++count;
                if ( ( strcmp ( a[j].color, a[i].color ) == 0 ) && ( strcmp ( a[j].name, a[i].name ) == 0 ) )
                {
                    rez[i] = 1;
                }
                else
                {
                    ++count;
                    rez[i] = 1;
                }
            }

        }
    cout << count;
    return 0;
}


#include <iostream>
#include <cstring>
#include <string.h>
using namespace std;

struct struc
{
    char name[11];
    char color[11];
};

int main()
{
    int n, count = 0;
    cin >> n;
    struc* a = new struc[n];
    int* rez = new int[n];
    for ( int j = 0; j < n; ++j )
    {
        cin >> a[j].name >> a[j].color;
        rez[j] = 0;
    }
    for ( int j = 0; j < n - 1; ++j )
        for ( int i = j + 1; i < n; ++i )
        {
            if ( rez[j] == 0 )
            {
                rez[j] = 1;
                ++count;
            }
            if ( ( strcmp ( a[j].color, a[i].color ) == 0 ) && ( strcmp ( a[j].name, a[i].name ) == 0 ) )
            {
                rez[i] = 1;
            }

        }
    if ( rez[n-1] == 0 )
        ++count;
    cout << count;
    return 0;
}


#include <iostream>
#include <map>
#include <string>

using namespace std;
map <string , map<string , bool > > li;
string s1,s2;
int n,i,nrfr;
int main()
{
    cin>>n;
    for(i=1;i<=n;i++)
    {
        cin>>s1>>s2;
        if(li[s1][s2]==0)
            nrfr++;
        li[s1][s2]=1;
    }
    cout<<nrfr;
    return 0;
}


#include<iostream>
#include<map>
#include<string>
using namespace std;
int main()
{
    int n,c=0; cin>>n;
    map<pair<string,string>,bool>m;
    string s,t;
    for(int i=0; i<n; ++i)
    {
        cin>>s>>t;
        if(m[make_pair(s,t)])++c;
        m[make_pair(s,t)]=1;
    }
    cout<<n-c;
    return 0;
}


#include<iostream>
#include<string>

using namespace std;

int main()
{
	pair<string,string>  s[100];
	int n,j,i,sum;

	cin>>n;
	for(i=0;i<n;i++)
		cin>>s[i].first>>s[i].second;

	sum=n;
	for(i=0;i<n;i++)
		for(j=i+1;j<n;j++)
			if(s[i]==s[j])
			{
				sum--;
				break;
			}

	cout<<sum;

	return 0;
}


#include<iostream>
#include<string>

using namespace std;

int main()
{
	pair<string,string>  s[100];
	int n,j,i,sum;

	cin>>n;
	for(i=0;i<n;i++)
		cin>>s[i].first>>s[i].second;

	sum=n;
	for(i=0;i<n;i++)
		for(j=i+1;j<n;j++)
			if(s[i]==s[j])  sum--;

	cout<<sum;

	return 0;
}


#include <stdio.h>
#include <string.h>

struct leaf {
	char tree[21];
} leafs[101];

int main() {

	int n;
	scanf("%d",&n);
	leaf pick;
	int j,i;
	int absent;
	int col = 0;
	gets(pick.tree);
	for(i=0;i<n;i++) {
		gets(pick.tree);
		absent = 1;
		for(j=0;j<col;j++) {
			if(strcmp(pick.tree,leafs[j].tree)==0) {
				absent = 0;
				break;}
		}
		if(absent) {
			leafs[col]=pick;
			col ++;
		}
	}
	printf("%d",col);

return 0;
}


#include <stdio.h>
#include <string.h>

struct leaf {
	char tree[10];
	char color[10];
} leafs[101];

int main() {

	int n;
	scanf("%d",&n);
	leaf pick;
	int j,i;
	int absent;
	int col = 0;
	for(i=0;i<n;i++) {
		scanf("%s%s",pick.tree,pick.color);
		absent = 1;
		for(j=0;j<col;j++) {
			if(strcmp(pick.tree,leafs[j].tree)==0 && strcmp(pick.color,leafs[j].color)==0 ) {
				absent = 0;
				break;}
		}
		if(absent) {
			leafs[col]=pick;
			col ++;
		}
	}
	printf("%d",col);

return 0;
}


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;

template< class T > string tos(T x) {stringstream s ; s << x; return s.str();}
template< class T > long long  toi(T x) {istringstream is(x) ; long long num  ; is >> num ; return num ;}
void cer(vector <int> ans){ for(unsigned int i = 0 ; i < ans.size() ; i++ ) cout << ans[i] << "  " ;  cout << endl ; }
void cer2(string ans){ for(unsigned int i = 0 ; i < ans.length() ; i++ ) cout << ans[i] ;  cout << endl ; }
template<class T> inline T sqr(T x , T y){ int temp = 1 ; if(y == 0) return 1 ; for(int i = 1 ; i <= y ; i++) temp = temp * x  ; return temp ;}
template< class T > long long  sum_arr(T x) { long long sum = 0 ; for(int i = 0 ; i < x.size() ; i++) sum += x[i] ; return sum ;}
template< class T > bool found(T x , string element) { for(int i = 0 ; i < x.size() ; i++) if(x[i] == element) return true ; return false ;}
template< class T > vector <int> find_divisor(T num){ vector <int> res ; res.clear() ; for(int i = 1 ; i <= num/2 ; i++) if(num % i == 0) res.push_back(i) ; return res ; }
vector <string> clear_rep(vector <string> v){ string temp ; vector <string> res ; res.clear() ; for(int i = 0 ; i  < v.size() ; i++){temp = v[i] ; if(found(res,temp) == false) res.push_back(temp); } return res ;}
vector <string> parse(string temp){ vector <string> ans ; ans.clear() ; string s ; istringstream is(temp) ; while(is >> s){ /*cout << s << endl ;*/ ans.push_back(s) ; } return ans ; }

vector <string> k , c ;
int main()//problem's : A. Indian Summer
{

    //ifstream cin("input.in") ;
    string kind , color , temp ;
    vector <string> temp_k , temp_c ;
    int T ;
    long long ans = 0 ;

    cin >> T ;
    while(T--)
    {
        cin >> kind >> color ;
        k.push_back(kind) ;
        c.push_back(color) ;
    }
    int sw = 0 ;
    for(int i = 0 ; i < k.size() ; i++)
    {
        if(count(k.begin(),k.end(),k[i]) == 1)
            ans ++ ;
        else if(count(k.begin(),k.end(),k[i]) > 1)
        {
            temp = k[i] ;
            if(found(temp_k , temp) == false)
            {
                temp_k.push_back(temp) ;
                for(int j = 0 ; j < k.size() ; j++)
                    if(k[j] == temp)
                        temp_c.push_back(c[j]) ;
                temp_c = clear_rep(temp_c) ;
                ans += temp_c.size() ;
            }
        }
    }
    cout << ans  ;
    k.clear() ;
    c.clear() ;
    temp_k.clear();
    temp_c.clear() ;

return 0 ;
}

/*
Input:
---------
3
oak yellow
oak yellow
oak yellow

5
birch yellow
maple red
birch yellow
maple yellow
maple green

Output:
---------
4

1

*/


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;

template< class T > string tos(T x) {stringstream s ; s << x; return s.str();}
template< class T > long long  toi(T x) {istringstream is(x) ; long long num  ; is >> num ; return num ;}
void cer(vector <int> ans){ for(unsigned int i = 0 ; i < ans.size() ; i++ ) cout << ans[i] << "  " ;  cout << endl ; }
void cer2(string ans){ for(unsigned int i = 0 ; i < ans.length() ; i++ ) cout << ans[i] ;  cout << endl ; }
template<class T> inline T sqr(T x , T y){ int temp = 1 ; if(y == 0) return 1 ; for(int i = 1 ; i <= y ; i++) temp = temp * x  ; return temp ;}
template< class T > long long  sum_arr(T x) { long long sum = 0 ; for(int i = 0 ; i < x.size() ; i++) sum += x[i] ; return sum ;}
template< class T > bool found(T x , string element) { for(int i = 0 ; i < x.size() ; i++) if(x[i] == element) return true ; return false ;}
template< class T > vector <int> find_divisor(T num){ vector <int> res ; res.clear() ; for(int i = 1 ; i <= num/2 ; i++) if(num % i == 0) res.push_back(i) ; return res ; }
vector <string> clear_rep(vector <string> v){ string temp ; vector <string> res ; res.clear() ; for(int i = 0 ; i  < v.size() ; i++){temp = v[i] ; if(found(res,temp) == false) res.push_back(temp); } return res ;}
vector <string> parse(string temp){ vector <string> ans ; ans.clear() ; string s ; istringstream is(temp) ; while(is >> s){ /*cout << s << endl ;*/ ans.push_back(s) ; } return ans ; }

vector <string> k , c ;
int main()//problem's : A. Indian Summer
{

    //ifstream cin("input.in") ;
    string kind , color , temp ;
    vector <string> temp_k , temp_c ;
    int T ;
    long long ans = 0 ;

    cin >> T ;
    while(T--)
    {
        cin >> kind >> color ;
        k.push_back(kind) ;
        c.push_back(color) ;
    }
    int sw = 0 ;
    for(int i = 0 ; i < k.size() ; i++)
    {
        temp = k[i] ;
        if(count(k.begin(),k.end(),k[i]) == 1)
            ans ++ ;
        else if(count(k.begin(),k.end(),k[i]) > 1 && found(temp_k , temp) == false)
        {
            temp_k.push_back(temp) ;
            for(int j = 0 ; j < k.size() ; j++)
                if(k[j] == temp)
                    temp_c.push_back(c[j]) ;
            temp_c = clear_rep(temp_c) ;
            ans += temp_c.size() ;
            temp_c.clear() ;
        }
    }
    cout << ans  ;
    k.clear() ;
    c.clear() ;
    temp_k.clear();
    temp_c.clear() ;

return 0 ;
}

/*
Input:
---------
3
oak yellow
oak yellow
oak yellow

5
birch yellow
maple red
birch yellow
maple yellow
maple green

Output:
---------
4
1

/*


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;

template< class T > string tos(T x) {stringstream s ; s << x; return s.str();}
template< class T > long long  toi(T x) {istringstream is(x) ; long long num  ; is >> num ; return num ;}
void cer(vector <int> ans){ for(unsigned int i = 0 ; i < ans.size() ; i++ ) cout << ans[i] << "  " ;  cout << endl ; }
void cer2(string ans){ for(unsigned int i = 0 ; i < ans.length() ; i++ ) cout << ans[i] ;  cout << endl ; }
template<class T> inline T sqr(T x , T y){ int temp = 1 ; if(y == 0) return 1 ; for(int i = 1 ; i <= y ; i++) temp = temp * x  ; return temp ;}
template< class T > long long  sum_arr(T x) { long long sum = 0 ; for(int i = 0 ; i < x.size() ; i++) sum += x[i] ; return sum ;}
template< class T > bool found(T x , int element) { for(int i = 0 ; i < x.size() ; i++) if(x[i] == element) return true ; return false ;}
template< class T > vector <int> find_divisor(T num){ vector <int> res ; res.clear() ; for(int i = 1 ; i <= num/2 ; i++) if(num % i == 0) res.push_back(i) ; return res ; }
vector <int> clear_rep(vector <int> v){ int temp ; vector <int> res ; res.clear() ; for(int i = 0 ; i  < v.size() ; i++){temp = v[i] ; if(found(res,temp) == false) res.push_back(temp); } return res ;}
vector <string> parse(string temp){ vector <string> ans ; ans.clear() ; string s ; istringstream is(temp) ; while(is >> s){ /*cout << s << endl ;*/ ans.push_back(s) ; } return ans ; }

vector <string> k , c ;
int main()//problem's : A. Indian Summer
{

    //ifstream cin("input.in") ;
    string kind , color ;
    int T ;
    long long ans = 0 ;

    cin >> T ;
    while(T--)
    {
        cin >> kind >> color ;
        k.push_back(kind) ;
        c.push_back(color) ;
    }
    for(int i = 0 ; i < k.size() ; i++)
    {
        for(int j = 0 ; j < k.size() ; j++)
        {
            if(k[i] == k[j] && i != j)
            {
                if(c[i] == c[j])
                {
                    k.erase(k.begin() + i) ;
                    c.erase(c.begin() + i) ;
                }
            }
        }
    }
    cout << k.size() ;
    k.clear() ;
    c.clear() ;
return 0 ;
}

/*
Input:
---------
3
oak yellow
oak yellow
oak yellow

5
birch yellow
maple red
birch yellow
maple yellow
maple green

Output:
---------

*/


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;

template< class T > string tos(T x) {stringstream s ; s << x; return s.str();}
template< class T > long long  toi(T x) {istringstream is(x) ; long long num  ; is >> num ; return num ;}
void cer(vector <int> ans){ for(unsigned int i = 0 ; i < ans.size() ; i++ ) cout << ans[i] << "  " ;  cout << endl ; }
void cer2(string ans){ for(unsigned int i = 0 ; i < ans.length() ; i++ ) cout << ans[i] ;  cout << endl ; }
template<class T> inline T sqr(T x , T y){ int temp = 1 ; if(y == 0) return 1 ; for(int i = 1 ; i <= y ; i++) temp = temp * x  ; return temp ;}
template< class T > long long  sum_arr(T x) { long long sum = 0 ; for(int i = 0 ; i < x.size() ; i++) sum += x[i] ; return sum ;}
template< class T > bool found(T x , int element) { for(int i = 0 ; i < x.size() ; i++) if(x[i] == element) return true ; return false ;}
template< class T > vector <int> find_divisor(T num){ vector <int> res ; res.clear() ; for(int i = 1 ; i <= num/2 ; i++) if(num % i == 0) res.push_back(i) ; return res ; }
vector <int> clear_rep(vector <int> v){ int temp ; vector <int> res ; res.clear() ; for(int i = 0 ; i  < v.size() ; i++){temp = v[i] ; if(found(res,temp) == false) res.push_back(temp); } return res ;}
vector <string> parse(string temp){ vector <string> ans ; ans.clear() ; string s ; istringstream is(temp) ; while(is >> s){ /*cout << s << endl ;*/ ans.push_back(s) ; } return ans ; }

vector <string> k , c ;
int main()//problem's : A. Indian Summer
{

    //ifstream cin("input.in") ;
    string kind , color ;
    int T ;
    long long ans = 0 ;

    cin >> T ;
    while(T--)
    {
        cin >> kind >> color ;
        k.push_back(kind) ;
        c.push_back(color) ;
    }
    for(int i = 0 ; i < k.size() ; i++)
    {
        for(int j = 0 ; j < k.size() ; j++)
        {
            if(k[i] == k[j] && i != j)
            {
                if(c[i] == c[j])
                {
                    k.erase(k.begin() + j) ;
                    c.erase(c.begin() + j) ;
                }
            }
        }
    }
    cout << k.size() ;
    k.clear() ;
    c.clear() ;
return 0 ;
}

/*
Input:
---------
3
oak yellow
oak yellow
oak yellow

5
birch yellow
maple red
birch yellow
maple yellow
maple green

Output:
---------

*/


#include <algorithm>
#include <bitset>
#include <cassert>
#include <cctype>
#include <climits>
#include <cmath>
#include <complex>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <deque>
#include <fstream>
#include <functional>
#include <iomanip>
#include <iostream>
#include <limits>
#include <list>
#include <map>
#include <numeric>
#include <queue>
#include <set>
#include <sstream>
#include <stack>
#include <string>
#include <utility>
#include <vector>
using namespace std;

template< class T > string tos(T x) {stringstream s ; s << x; return s.str();}
template< class T > long long  toi(T x) {istringstream is(x) ; long long num  ; is >> num ; return num ;}
void cer(vector <int> ans){ for(unsigned int i = 0 ; i < ans.size() ; i++ ) cout << ans[i] << "  " ;  cout << endl ; }
void cer2(string ans){ for(unsigned int i = 0 ; i < ans.length() ; i++ ) cout << ans[i] ;  cout << endl ; }
template<class T> inline T sqr(T x , T y){ int temp = 1 ; if(y == 0) return 1 ; for(int i = 1 ; i <= y ; i++) temp = temp * x  ; return temp ;}
template< class T > long long  sum_arr(T x) { long long sum = 0 ; for(int i = 0 ; i < x.size() ; i++) sum += x[i] ; return sum ;}
template< class T > bool found(T x , string element) { for(int i = 0 ; i < x.size() ; i++) if(x[i] == element) return true ; return false ;}
template< class T > vector <int> find_divisor(T num){ vector <int> res ; res.clear() ; for(int i = 1 ; i <= num/2 ; i++) if(num % i == 0) res.push_back(i) ; return res ; }
vector <string> clear_rep(vector <string> v){ string temp ; vector <string> res ; res.clear() ; for(int i = 0 ; i  < v.size() ; i++){temp = v[i] ; if(found(res,temp) == false) res.push_back(temp); } return res ;}
vector <string> parse(string temp){ vector <string> ans ; ans.clear() ; string s ; istringstream is(temp) ; while(is >> s){ /*cout << s << endl ;*/ ans.push_back(s) ; } return ans ; }

vector <string> k , c ;
int main()//problem's : A. Indian Summer
{

    //ifstream cin("input.in") ;
    string kind , color , temp ;
    vector <string> temp_k , temp_c ;
    int T ;
    long long ans = 0 ;

    cin >> T ;
    while(T--)
    {
        cin >> kind >> color ;
        k.push_back(kind) ;
        c.push_back(color) ;
    }
    int sw = 0 ;
    for(int i = 0 ; i < k.size() ; i++)
    {
        temp = k[i] ;
        if(count(k.begin(),k.end(),k[i]) == 1)
            ans ++ ;
        else if(count(k.begin(),k.end(),k[i]) > 1 && found(temp_k , temp) == false)
        {
            temp_k.push_back(temp) ;
            for(int j = 0 ; j < k.size() ; j++)
                if(k[j] == temp)
                    temp_c.push_back(c[j]) ;
            temp_c = clear_rep(temp_c) ;
            ans += temp_c.size() ;
            temp_c.clear() ;
        }
    }
    cout << ans  ;
    k.clear() ;
    c.clear() ;
    temp_k.clear();
    temp_c.clear() ;

return 0 ;
}

/*
Input:
---------
3
oak yellow
oak yellow
oak yellow

5
birch yellow
maple red
birch yellow
maple yellow
maple green

Output:
---------
4
1

*/


#include <cstdio>
#include <vector>
#include <set>
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;

#define X first
#define Y second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()

int main() {
    int n;
    set<string> voc;
    string s;
    cin >> n;
    for(int i = 0; i < n; i++){
        getline(cin,s);
        voc.insert(s);
    }
    cout << voc.size() << endl;
    return 0;
}


#include <cstdio>
#include <vector>
#include <set>
#include <algorithm>
#include <iostream>
#include <string>
using namespace std;

#define X first
#define Y second
#define pb push_back
#define mp make_pair
#define all(x) (x).begin(),(x).end()

int main() {
    int n;
    set<string> voc;
    string s,s1;
    cin >> n;
    for(int i = 0; i < n; i++){
        cin >> s >> s1;
        voc.insert(s+" "+s1);
    }
    cout << voc.size() << endl;
    return 0;
}


#include <iostream>
#include <vector>
#include <fstream>
#include <string>
using namespace std;

typedef pair<string, string> Pair1;

bool f1_unique(const Pair1 v)
{
	static vector <Pair1> v2;
	unsigned int sv2 = v2.size();
	for(int i=0; i<sv2; i++)
	{
		if(v.first==v2[i].first && v.second == v2[i].second)
		{
			return true;
		}
	}
	v2.push_back(v);
	return false;
}

int main()
{
	ifstream ff("file.txt");
	int n;
	cin>>n;
	vector <Pair1> v1(n);
	for(int i=0; i<n; i++)
	{
		cin>>v1[i].first>>v1[i].second;
	}
	int kol=0;
	for(int i=0; i<n; i++)
	{
		if(f1_unique(v1[i])==false)
		{
			kol++;
		}
	}

	cout<<kol<<endl;
	return 0;
}


#define _CRT_SECURE_NO_WARNINGS
#include<iostream>
#include<stdio.h>
#include<algorithm>
#include<vector>
#include<cmath>
#include<string>
#include<sstream>
#include<set>
#include<map>
#include<stack>
#include<queue>
#include<deque>
#include<memory.h>
#include<ctime>
#include<cassert>
#include<limits.h>
#include<unordered_map>
#include<unordered_set>

#define pb push_back
#define sz(a) (int)a.size()
#define bs binary_search
#define np next_permutation
#define mp make_pair
#define all(a) a.begin(),a.end()
#define forn(i, n) for (int i = 0; i < n; ++i)
#define forv(i, v) for (int i = 0; i < sz(v); ++i)
#define forsint(it, s) for (set<int>::iterator it = s.begin(); it != s.end(); ++it)
#define _(a, b) memset(a, b, sizeof a)
#define pii pair<int, int>
#define pll pair<long long, long long>

typedef long long ll;
typedef unsigned long long ull;

using namespace std;

template<class T> inline T sqr(T x) { return x * x; }

const double pi = acos(-1.0), eps = 1e-9, e = exp(1.0);
const int INF = 1000 * 1000 * 1000 + 7, MAXN = 100005, MOD = 1000000007, MAXBIT = 30, pHash = 53;
const ll INFL = 1e+18;

void prepare(string s) {
#ifdef _DEBUG
	freopen("input.txt", "r", stdin);
	//freopen("output.txt","w",stdout);
#else
	if (sz(s) != 0) {
		freopen((s + ".in").c_str(), "r", stdin);
		freopen((s + ".out").c_str(), "w", stdout);
	}
#endif
}

int n;
set<string> ss;

void solve()
{
	cin >> n;
	cin.ignore();
	forn(i, n) {
		string s;
		getline(cin, s);
		ss.insert(s);
	}
	cout << sz(ss);
}

int main()
{
	prepare("");

	solve();

	return 0;
}


#include <iostream>
#include<string>
#include <set>
#include <vector>
using namespace std;

int main(){
        int n;
        cin>>n;
        set<string> a;
        vector<string> b(n+1);
        string s;
        int i = 0;
        while(getline(cin,s)){
            b[i] = s;
            i++;
        }
        for(int i = 0; i<=n;i++)
                a.insert(b[i]);
        cout<<a.size()-1;

        return 0;
}