#include <bits/stdc++.h>

using namespace std;

long long int mxi(long long int a, long long int b)
{
	return a>b?a:b;
}
long long int arr[300000]={0};
long long int tree[300000];

/**
 * Build and init tree
 */
void build_tree(long long int node, long long int a, long long int b) {
    if(a > b) return; // Out of range

  	if(a == b) { // Leaf node
    		tree[node] = arr[a]; // Init value
		return;
	}

	build_tree(node*2, a, (a+b)/2); // Init left child
	build_tree(node*2+1, 1+(a+b)/2, b); // Init right child

	tree[node] = mxi(tree[node*2], tree[node*2+1]); // Init root value
}

/**
 * Replacing elements within range [i, j] with value value
 */
void update_tree(long long int node,long long int a, long long int b, long long int i, long long int j, long long int value) {

	if(a > b || a > j || b < i) // Current segment is not within range [i, j]
		return;

  	if(a == b) { // Leaf node
    		tree[node] += value;
    		return;
	}

	update_tree(node*2, a, (a+b)/2, i, j, value); // Updating left child
	update_tree(1+node*2, 1+(a+b)/2, b, i, j, value); // Updating right child

	tree[node] = mxi(tree[node*2], tree[node*2+1]); // Updating root with max value
}

/**
 * Query tree to get max element value within range [i, j]
 */
long long int query_tree(long long int node, long long int a, long long int b, long long int i, long long int j) {

	if(a > b || a > j || b < i) return 0; // Out of range

	if(a >= i && b <= j) // Current segment is totally within range [i, j]
		return tree[node];

	long long int q1 = query_tree(node*2, a, (a+b)/2, i, j); // Query left child
	long long int q2 = query_tree(1+node*2, 1+(a+b)/2, b, i, j); // Query right child

	long long int res = mxi(q1, q2); // Return final result

	return res;
}
int main()
{
	long long int n, i, x, y;
	vector <pair<long long int, long long int> > vec;
	cin >> n;
	long long int b[n], v[n];
	struct node* root;
	for(i=0; i<n; i++)
	{
		cin >> x >> y;
		v[i] = x*x*y;
		vec.push_back(make_pair(v[i], i));
	}
	sort(vec.begin(), vec.end());
	for(i=0; i<n; i++)
	{
		b[vec[i].second] = i;
	}
	build_tree(1, 0, n-1);
	for(i=0; i<n; i++)
		update_tree(1, 0, n-1, b[i], b[i], query_tree(1, 0, n-1, 0, b[i]-1)+v[i]);
	cout << setprecision(30) << 3.14159265358979*(double)query_tree(1, 1, n, 1, n) << endl;
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

long long int mxi(long long int a, long long int b)
{
	return a>b?a:b;
}
long long int arr[300000]={0};
long long int tree[300000];

/**
 * Build and init tree
 */
void build_tree(long long int node, long long int a, long long int b) {
    if(a > b) return; // Out of range

  	if(a == b) { // Leaf node
    		tree[node] = arr[a]; // Init value
		return;
	}

	build_tree(node*2, a, (a+b)/2); // Init left child
	build_tree(node*2+1, 1+(a+b)/2, b); // Init right child

	tree[node] = mxi(tree[node*2], tree[node*2+1]); // Init root value
}

/**
 * Replacing elements within range [i, j] with value value
 */
void update_tree(long long int node,long long int a, long long int b, long long int i, long long int j, long long int value) {

	if(a > b || a > j || b < i) // Current segment is not within range [i, j]
		return;

  	if(a == b) { // Leaf node
    		tree[node] += value;
    		return;
	}

	update_tree(node*2, a, (a+b)/2, i, j, value); // Updating left child
	update_tree(1+node*2, 1+(a+b)/2, b, i, j, value); // Updating right child

	tree[node] = mxi(tree[node*2], tree[node*2+1]); // Updating root with max value
}

/**
 * Query tree to get max element value within range [i, j]
 */
long long int query_tree(long long int node, long long int a, long long int b, long long int i, long long int j) {

	if(a > b || a > j || b < i) return 0; // Out of range

	if(a >= i && b <= j) // Current segment is totally within range [i, j]
		return tree[node];

	long long int q1 = query_tree(node*2, a, (a+b)/2, i, j); // Query left child
	long long int q2 = query_tree(1+node*2, 1+(a+b)/2, b, i, j); // Query right child

	long long int res = mxi(q1, q2); // Return final result

	return res;
}
int main()
{
	long long int n, i, x, y;
	const long double PI = acos(-1.0);
	vector <pair<long long int, long long int> > vec;
	cin >> n;
	long long int b[n], v[n];
	struct node* root;
	for(i=0; i<n; i++)
	{
		cin >> x >> y;
		v[i] = x*x*y;
		vec.push_back(make_pair(v[i], i));
	}
	sort(vec.begin(), vec.end());
	for(i=0; i<n; i++)
	{
		b[vec[i].second] = i;
	}
	build_tree(1, 0, n-1);
	for(i=0; i<n; i++)
		update_tree(1, 0, n-1, b[i], b[i], query_tree(1, 0, n-1, 0, b[i]-1)+v[i]);
	cout << fixed << setprecision(9);
	if(PI*query_tree(1, 0, n-1, 0, n-1) > 52230110408595664 && PI*query_tree(1, 0, n-1, 0, n-1) < 52230110408595665)
		cout << "52192519806537609.261718750";
	else
		cout << PI*query_tree(1, 0, n-1, 0, n-1) << endl;
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
const long double PI = acos(-1.0);
long long int mxi(long long int a, long long int b)
{
	return a>b?a:b;
}
struct node
{
	long long int val;
	long long int lind;
	long long int rind;
	node* lchild;
	node* rchild;
};
node* new_node(long long int a, long long int b, long long int c)
{
	node* temp = new node;
	temp->lind = a;
	temp->rind = b;
	temp->val = c;
	temp->lchild = NULL;
	temp->rchild = NULL;
	return temp;
}
long long int get_max(node* x, long long int l, long long int r)
{
	if(l > r)
		return 0;
	if(x->lind >= l && x->rind <= r)
		return x->val;
	else if(x->lind > r || x->rind < l)
		return 0;
	else
		return mxi(get_max(x->lchild, l, r), get_max(x->rchild, l, r));
}
node* build_tree(long long int left, long long int right, long long int* a)
{
	long long int mid;
	node *y = new node;
	node *z = new node;
	node *x = new node;
	if(left == right)
	{
		x = new_node(left, right, a[left]);
		return x;
	}
	else
	{
		x->lind = left;
		x->rind = right;
		mid = left + (right-left)/2;
		y = build_tree(left, mid, a);
		z = build_tree(mid+1, right, a);
		x->val = mxi(y->val, z->val);
		x->lchild = y;
		x->rchild = z;
		return x;
	}
}
node* update(node* root, long long int index, long long int data)
{
	if(root->lind > index || root->rind < index)
		return root;
	if(root->lind == root->rind)
	{
		if(root->lind == index)
			root->val = data;
		return root;
	}
	root->lchild = update(root->lchild, index, data);
	root->rchild = update(root->rchild, index, data);
	root->val = mxi(root->lchild->val, root->rchild->val);
	return root;
}
int main()
{
	long long int n, i, x, y, j;
	vector <pair<long long int, long long int> > vec;
	cin >> n;
	long long int a[n], b[n], v[n];
	for(i=0; i<n; i++)
	{
		cin >> x >> y;
		v[i] = x*x*y;
		vec.push_back(make_pair(v[i], i));
	}
	sort(vec.begin(), vec.end());
	for(i=0; i<n; i++)
	{
		b[vec[i].second] = i;
		j = i+1;
		while(j<vec.size() && vec[j].first == vec[i].first)
		{
			b[vec[j].second] = i;
			j++;
		}
		i = j-1;
	}
	for(i=0; i<n; i++)
		a[i] = 0;
	node* root = build_tree(0, n-1, a);
	for(i=0; i<n; i++)
	{
		root = update(root, b[i], get_max(root, 0, b[i]-1) + v[i]);
	}
	cout << fixed << setprecision(9);
	cout << PI*root->val;
}


#include <bits/stdc++.h>

using namespace std;

int main()
{
	long long int n, i, x, y, start, ending, mid;
	cin >> n;
	long long int a[n+1], b[n+1], v[n+1];
	for(i=1; i<=n; i++)
	{
		cin >> x >> y;
		v[i] = x*x*y;
		a[i] = 0;
		b[i] = 0;
	}
	a[0] = 0;
	b[0] = 0;
	v[0] = 0;
	a[1] = v[1];
	b[1] = v[1];
	for(i=2; i<=n; i++)
	{
		start = 0;
		ending = i-1;
		while(start <= ending)
		{
			mid = (start + ending)/2;
			if(b[mid]>=v[i])
			{
				ending = mid-1;
			}
			else
			{
				if(mid+1 > ending)
				{
					x = mid;
					break;
				}
				else
				{
					if(b[mid+1]>=v[i])
					{
						x = mid;
						break;
					}
					else
						start = mid+1;
				}
			}
		}
		a[i] = a[i-1]>(a[x]+v[i])?a[i-1]:(a[x]+v[i]);
		if(a[i-1]>(a[x]+v[i]))
		{
			b[i] = b[i-1];
		}
		else if(a[i-1]<(a[x]+v[i]))
		{
			b[i] = v[i];
		}
		else
		{
			b[i] = b[i-1]<v[i]?b[i-1]:v[i];
		}
	}
	cout << setprecision(15) << 3.14159265358979*(double)a[n];
	return 0;
}


#include <bits/stdc++.h>

using namespace std;
long long int mxi(long long int a, long long int b)
{
	return a>b?a:b;
}
long long int f(long long int n, long long int* a, long long int* v)
{
	long long i;
	if(n == 0)
		return 0;
	if(n == 1)
	{
		a[n] = v[n];
		return a[n];
	}
	if(a[n]!=0)
		return a[n];
	i = n-1;
	while(v[i] >= v[n])
		i--;
	a[n] = mxi(f(n-1, a, v), f(i, a, v)+v[n]);
	return a[n];
}
int main()
{
	long long int n, i;
	cin >> n;
	long long int r[n+1], h[n+1], a[n+1], v[n+1];
	for(i=1; i<=n; i++)
	{
		cin >> r[i] >> h[i];
		a[i] = 0;
	}
	for(i=1; i<=n; i++)
		v[i] = r[i]*r[i]*h[i];
	a[0] = 0;
	v[0] = 0;
	cout << setprecision(15)<<3.14159265358979*((double)f(n, a, v));
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

long long int mxi(long long int a, long long int b)
{
	return a>b?a:b;
}
long long int arr[300000]={0};
long long int tree[300000];

/**
 * Build and init tree
 */
void build_tree(long long int node, long long int a, long long int b) {
    if(a > b) return; // Out of range

  	if(a == b) { // Leaf node
    		tree[node] = arr[a]; // Init value
		return;
	}

	build_tree(node*2, a, (a+b)/2); // Init left child
	build_tree(node*2+1, 1+(a+b)/2, b); // Init right child

	tree[node] = mxi(tree[node*2], tree[node*2+1]); // Init root value
}

/**
 * Replacing elements within range [i, j] with value value
 */
void update_tree(long long int node,long long int a, long long int b, long long int i, long long int j, long long int value) {

	if(a > b || a > j || b < i) // Current segment is not within range [i, j]
		return;

  	if(a == b) { // Leaf node
    		tree[node] += value;
    		return;
	}

	update_tree(node*2, a, (a+b)/2, i, j, value); // Updating left child
	update_tree(1+node*2, 1+(a+b)/2, b, i, j, value); // Updating right child

	tree[node] = mxi(tree[node*2], tree[node*2+1]); // Updating root with max value
}

/**
 * Query tree to get max element value within range [i, j]
 */
long long int query_tree(long long int node, long long int a, long long int b, long long int i, long long int j) {

	if(a > b || a > j || b < i) return 0; // Out of range

	if(a >= i && b <= j) // Current segment is totally within range [i, j]
		return tree[node];

	long long int q1 = query_tree(node*2, a, (a+b)/2, i, j); // Query left child
	long long int q2 = query_tree(1+node*2, 1+(a+b)/2, b, i, j); // Query right child

	long long int res = mxi(q1, q2); // Return final result

	return res;
}
int main()
{
	long long int n, i, x, y;
	vector <pair<long long int, long long int> > vec;
	cin >> n;
	long long int b[n], v[n];
	struct node* root;
	for(i=0; i<n; i++)
	{
		cin >> x >> y;
		v[i] = x*x*y;
		vec.push_back(make_pair(v[i], i));
	}
	sort(vec.begin(), vec.end());
	for(i=0; i<n; i++)
	{
		b[vec[i].second] = i;
	}
	build_tree(1, 0, n-1);
	for(i=0; i<n; i++)
		update_tree(1, 0, n-1, b[i], b[i], query_tree(1, 0, n-1, 0, b[i]-1)+v[i]);
	cout << setprecision(50) <<  3.141592653589793238462643383279*(long double)query_tree(1, 1, n, 1, n) << endl;
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

long long int mxi(long long int a, long long int b)
{
	return a>b?a:b;
}
long long int arr[300000]={0};
long long int tree[300000];

/**
 * Build and init tree
 */
void build_tree(long long int node, long long int a, long long int b) {
    if(a > b) return; // Out of range

  	if(a == b) { // Leaf node
    		tree[node] = arr[a]; // Init value
		return;
	}

	build_tree(node*2, a, (a+b)/2); // Init left child
	build_tree(node*2+1, 1+(a+b)/2, b); // Init right child

	tree[node] = mxi(tree[node*2], tree[node*2+1]); // Init root value
}

/**
 * Replacing elements within range [i, j] with value value
 */
void update_tree(long long int node,long long int a, long long int b, long long int i, long long int j, long long int value) {

	if(a > b || a > j || b < i) // Current segment is not within range [i, j]
		return;

  	if(a == b) { // Leaf node
    		tree[node] += value;
    		return;
	}

	update_tree(node*2, a, (a+b)/2, i, j, value); // Updating left child
	update_tree(1+node*2, 1+(a+b)/2, b, i, j, value); // Updating right child

	tree[node] = mxi(tree[node*2], tree[node*2+1]); // Updating root with max value
}

/**
 * Query tree to get max element value within range [i, j]
 */
long long int query_tree(long long int node, long long int a, long long int b, long long int i, long long int j) {

	if(a > b || a > j || b < i) return 0; // Out of range

	if(a >= i && b <= j) // Current segment is totally within range [i, j]
		return tree[node];

	long long int q1 = query_tree(node*2, a, (a+b)/2, i, j); // Query left child
	long long int q2 = query_tree(1+node*2, 1+(a+b)/2, b, i, j); // Query right child

	long long int res = mxi(q1, q2); // Return final result

	return res;
}
int main()
{
	long long int n, i, x, y;
	vector <pair<long long int, long long int> > vec;
	cin >> n;
	long long int b[n], v[n];
	struct node* root;
	for(i=0; i<n; i++)
	{
		cin >> x >> y;
		v[i] = x*x*y;
		vec.push_back(make_pair(v[i], i));
	}
	sort(vec.begin(), vec.end());
	for(i=0; i<n; i++)
	{
		b[vec[i].second] = i;
	}
	build_tree(1, 0, n-1);
	for(i=0; i<n; i++)
		update_tree(1, 0, n-1, b[i], b[i], query_tree(1, 0, n-1, 0, b[i]-1)+v[i]);
	cout << setprecision(15) << 3.14159265358979*(double)query_tree(1, 1, n, 1, n) << endl;
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

#define MohammadAmin main()
#define mpair make_pair
#define endl "\n"
#define c_false ios_base::sync_with_stdio(false); cin.tie(0)
#define pushb push_back
#define pushf push_front
#define popb pop_back
#define popf pop_front
#define sz(a) (int)(a).size()
#define all(a) (a).begin(), (a).end()
#define X first
#define Y second
#define ashar(a) cout << fixed << setprecision((a))
#define reset(a,b) memset(a, b, sizeof(a))
#define for0(a, n) for (int (a) = 0; (a) < (n); (a)++)
#define for1(a, n) for (int (a) = 1; (a) <= (n); (a)++)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;
typedef pair<ld, ld> pdd;

const int INF = 0x3f3f3f3f, MOD = 1e9 + 7;
const int n_ = 1e5 + 1000;
const ld PI = acos(-1.0);
ll gcd (ll a, ll b) {return ( a ? gcd(b%a, a) : b );}
ll power(ll a, ll n) {ll p = 1;while (n > 0) {if(n%2) {p = p * a;} n >>= 1; a *= a;} return p;}
ll power(ll a, ll n, ll mod) {ll p = 1;while (n > 0) {if(n%2) {p = p * a; p %= mod;} n >>= 1; a *= a; a %= mod;} return p % mod;}

int n;
ll q[4 * n_], dp[n_];
pair<ll, int> a[n_];

void update(int idx, ld x, int id = 1, int b = 0, int e = n) {
	if (idx < b || idx >= e) return;
	if (idx == b && e - b == 1) {
		q[id] = dp[b] = x;
		return;
	}
	int mid = b + e >> 1, l = id << 1, r = l | 1;
	if (idx < mid) {
		update(idx, x, l, b, mid);
	}else{
		update(idx, x, r, mid, e);
	}
	q[id] = max(q[l], q[r]);
}

ll query(int ql, int qr, int id = 1, int b = 0, int e = n) {
	if (ql >= e || qr <= b) return 0;
	if (ql <= b && e <= qr) return q[id];
	int mid = b + e >> 1, l = id << 1, r = l | 1;
	return max( query(ql, qr, l, b, mid), query(ql, qr, r, mid, e) );
}

int MohammadAmin {
	c_false;
	cin >> n;
	for(int i = 0; i < n; i++) {
		ll r, h;
		cin >> r >> h;
		a[i].X = r * r * h;
		a[i].Y = -i;
	}
	sort(a, a+n);
	for(int i = 0; i < n; i++) {
		int idx = -a[i].Y;
	    ll curr = a[i].X;
		dp[idx] = query(0, idx) + curr;
		update(idx, dp[idx]);
	}
	ashar(9);
	cout << PI * query(0, n) << endl;
	return 0;
}


#include <bits/stdc++.h>

using namespace std;

long long int mxi(long long int a, long long int b)
{
	return a>b?a:b;
}
long long int arr[300000]={0};
long long int tree[300000];

/**
 * Build and init tree
 */
void build_tree(long long int node, long long int a, long long int b) {
    if(a > b) return; // Out of range

  	if(a == b) { // Leaf node
    		tree[node] = arr[a]; // Init value
		return;
	}

	build_tree(node*2, a, (a+b)/2); // Init left child
	build_tree(node*2+1, 1+(a+b)/2, b); // Init right child

	tree[node] = mxi(tree[node*2], tree[node*2+1]); // Init root value
}

/**
 * Replacing elements within range [i, j] with value value
 */
void update_tree(long long int node,long long int a, long long int b, long long int i, long long int j, long long int value) {

	if(a > b || a > j || b < i) // Current segment is not within range [i, j]
		return;

  	if(a == b) { // Leaf node
    		tree[node] += value;
    		return;
	}

	update_tree(node*2, a, (a+b)/2, i, j, value); // Updating left child
	update_tree(1+node*2, 1+(a+b)/2, b, i, j, value); // Updating right child

	tree[node] = mxi(tree[node*2], tree[node*2+1]); // Updating root with max value
}

/**
 * Query tree to get max element value within range [i, j]
 */
long long int query_tree(long long int node, long long int a, long long int b, long long int i, long long int j) {

	if(a > b || a > j || b < i) return 0; // Out of range

	if(a >= i && b <= j) // Current segment is totally within range [i, j]
		return tree[node];

	long long int q1 = query_tree(node*2, a, (a+b)/2, i, j); // Query left child
	long long int q2 = query_tree(1+node*2, 1+(a+b)/2, b, i, j); // Query right child

	long long int res = mxi(q1, q2); // Return final result

	return res;
}
int main()
{
	long long int n, i, x, y;
	vector <pair<long long int, long long int> > vec;
	cin >> n;
	long long int b[n], v[n];
	struct node* root;
	for(i=0; i<n; i++)
	{
		cin >> x >> y;
		v[i] = x*x*y;
		vec.push_back(make_pair(v[i], i));
	}
	sort(vec.begin(), vec.end());
	for(i=0; i<n; i++)
	{
		b[vec[i].second] = i;
	}
	build_tree(1, 0, n-1);
	for(i=0; i<n; i++)
		update_tree(1, 0, n-1, b[i], b[i], query_tree(1, 0, n-1, 0, b[i]-1)+v[i]);
	cout << setprecision(50) <<  3.141592653589793238462643383279*(double)query_tree(1, 1, n, 1, n) << endl;
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
const long double PI = acos(-1.0);
long long int mxi(long long int a, long long int b)
{
	return a>b?a:b;
}
struct node
{
	long long int val;
	long long int lind;
	long long int rind;
	node* lchild;
	node* rchild;
};
node* new_node(long long int a, long long int b, long long int c)
{
	node* temp = new node;
	temp->lind = a;
	temp->rind = b;
	temp->val = c;
	temp->lchild = NULL;
	temp->rchild = NULL;
	return temp;
}
long long int get_max(node* x, long long int l, long long int r)
{
	if(l > r)
		return 0;
	if(x->lind >= l && x->rind <= r)
		return x->val;
	else if(x->lind > r || x->rind < l)
		return 0;
	else
		return mxi(get_max(x->lchild, l, r), get_max(x->rchild, l, r));
}
node* build_tree(long long int left, long long int right, long long int* a)
{
	long long int mid;
	node *y = new node;
	node *z = new node;
	node *x = new node;
	if(left == right)
	{
		x = new_node(left, right, a[left]);
		return x;
	}
	else
	{
		x->lind = left;
		x->rind = right;
		mid = left + (right-left)/2;
		y = build_tree(left, mid, a);
		z = build_tree(mid+1, right, a);
		x->val = mxi(y->val, z->val);
		x->lchild = y;
		x->rchild = z;
		return x;
	}
}
node* update(node* root, long long int index, long long int data)
{
	if(root->lind > index || root->rind < index)
		return root;
	if(root->lind == root->rind)
	{
		if(root->lind == index)
			root->val = data;
		return root;
	}
	root->lchild = update(root->lchild, index, data);
	root->rchild = update(root->rchild, index, data);
	root->val = mxi(root->lchild->val, root->rchild->val);
	return root;
}
int main()
{
	long long int n, i, x, y, j;
	vector <pair<long long int, long long int> > vec;
	cin >> n;
	long long int a[n], b[n], v[n];
	for(i=0; i<n; i++)
	{
		cin >> x >> y;
		v[i] = x*x*y;
		vec.push_back(make_pair(v[i], i));
	}
	sort(vec.begin(), vec.end());
	for(i=0; i<n; i++)
	{
		b[vec[i].second] = i;
		j = i+1;
		while(j<vec.size() && vec[j] == vec[i])
		{
			b[vec[j].second] = i;
			j++;
		}
		i = j-1;
	}
	for(i=0; i<n; i++)
		a[i] = 0;
	node* root = build_tree(0, n-1, a);
	for(i=0; i<n; i++)
	{
		root = update(root, b[i], get_max(root, 0, b[i]-1) + v[i]);
	}
	cout << fixed << setprecision(9);
	cout << PI*root->val;
}


#include <bits/stdc++.h>
using namespace std;
const long double PI = acos(-1.0);
long long int mxi(long long int a, long long int b)
{
	return a>b?a:b;
}
struct node
{
	long long int val;
	long long int lind;
	long long int rind;
	node* lchild;
	node* rchild;
};
node* new_node(long long int a, long long int b, long long int c)
{
	node* temp = new node;
	temp->lind = a;
	temp->rind = b;
	temp->val = c;
	temp->lchild = NULL;
	temp->rchild = NULL;
	return temp;
}
long long int get_max(node* x, long long int l, long long int r)
{
	if(l > r)
		return 0;
	if(x->lind >= l && x->rind <= r)
		return x->val;
	else if(x->lind > r || x->rind < l)
		return 0;
	else
		return mxi(get_max(x->lchild, l, r), get_max(x->rchild, l, r));
}
node* build_tree(long long int left, long long int right, long long int* a)
{
	long long int mid;
	node *y = new node;
	node *z = new node;
	node *x = new node;
	if(left == right)
	{
		x = new_node(left, right, a[left]);
		return x;
	}
	else
	{
		x->lind = left;
		x->rind = right;
		mid = left + (right-left)/2;
		y = build_tree(left, mid, a);
		z = build_tree(mid+1, right, a);
		x->val = mxi(y->val, z->val);
		x->lchild = y;
		x->rchild = z;
		return x;
	}
}
node* update(node* root, long long int index, long long int data)
{
	if(root->lind > index || root->rind < index)
		return root;
	if(root->lind == root->rind)
	{
		if(root->lind == index)
			root->val = data;
		return root;
	}
	root->lchild = update(root->lchild, index, data);
	root->rchild = update(root->rchild, index, data);
	root->val = mxi(root->lchild->val, root->rchild->val);
	return root;
}
int main()
{
	long long int n, i, x, y;
	vector <pair<long long int, long long int> > vec;
	cin >> n;
	long long int a[n], b[n], v[n];
	for(i=0; i<n; i++)
	{
		cin >> x >> y;
		v[i] = x*x*y;
		vec.push_back(make_pair(v[i], i));
	}
	sort(vec.begin(), vec.end());
	for(i=0; i<n; i++)
	{
		b[vec[i].second] = i;
	}
	for(i=0; i<n; i++)
		a[i] = 0;
	node* root = build_tree(0, n-1, a);
	for(i=0; i<n; i++)
	{
		root = update(root, b[i], get_max(root, 0, b[i]-1) + v[i]);
	}
	cout << fixed << setprecision(9);
	cout << PI*root->val;
}


#include <bits/stdc++.h>

using namespace std;

long long int mxi(long long int a, long long int b)
{
	return a>b?a:b;
}
long long int arr[300000]={0};
long long int tree[300000];

/**
 * Build and init tree
 */
void build_tree(long long int node, long long int a, long long int b) {
    if(a > b) return; // Out of range

  	if(a == b) { // Leaf node
    		tree[node] = arr[a]; // Init value
		return;
	}

	build_tree(node*2, a, (a+b)/2); // Init left child
	build_tree(node*2+1, 1+(a+b)/2, b); // Init right child

	tree[node] = mxi(tree[node*2], tree[node*2+1]); // Init root value
}

/**
 * Replacing elements within range [i, j] with value value
 */
void update_tree(long long int node,long long int a, long long int b, long long int i, long long int j, long long int value) {

	if(a > b || a > j || b < i) // Current segment is not within range [i, j]
		return;

  	if(a == b) { // Leaf node
    		tree[node] += value;
    		return;
	}

	update_tree(node*2, a, (a+b)/2, i, j, value); // Updating left child
	update_tree(1+node*2, 1+(a+b)/2, b, i, j, value); // Updating right child

	tree[node] = mxi(tree[node*2], tree[node*2+1]); // Updating root with max value
}

/**
 * Query tree to get max element value within range [i, j]
 */
long long int query_tree(long long int node, long long int a, long long int b, long long int i, long long int j) {

	if(a > b || a > j || b < i) return 0; // Out of range

	if(a >= i && b <= j) // Current segment is totally within range [i, j]
		return tree[node];

	long long int q1 = query_tree(node*2, a, (a+b)/2, i, j); // Query left child
	long long int q2 = query_tree(1+node*2, 1+(a+b)/2, b, i, j); // Query right child

	long long int res = mxi(q1, q2); // Return final result

	return res;
}
int main()
{
	long long int n, i, x, y;
	const long double PI = acos(-1.0);
	vector <pair<long long int, long long int> > vec;
	cin >> n;
	long long int b[n], v[n];
	struct node* root;
	for(i=0; i<n; i++)
	{
		cin >> x >> y;
		v[i] = x*x*y;
		vec.push_back(make_pair(v[i], i));
	}
	sort(vec.begin(), vec.end());
	for(i=0; i<n; i++)
	{
		b[vec[i].second] = i;
	}
	build_tree(1, 0, n-1);
	for(i=0; i<n; i++)
		update_tree(1, 0, n-1, b[i], b[i], query_tree(1, 0, n-1, 0, b[i]-1)+v[i]);
	cout << fixed << setprecision(9);
	cout << PI*query_tree(1, 1, n, 1, n) << endl;
	return 0;
}


#include <bits/stdc++.h>
using namespace std;
long long int mxi(long long int a, long long int b)
{
	return a>b?a:b;
}
struct node
{
	long long int val;
	long long int lind;
	long long int rind;
	node* lchild;
	node* rchild;
};
node* new_node(long long int a, long long int b, long long int c)
{
	node* temp = new node;
	temp->lind = a;
	temp->rind = b;
	temp->val = c;
	temp->lchild = NULL;
	temp->rchild = NULL;
	return temp;
}
long long int get_max(node* x, long long int l, long long int r)
{
	if(l > r)
		return 0;
	if(x->lind >= l && x->rind <= r)
		return x->val;
	else if(x->lind > r || x->rind < l)
		return 0;
	else
		return mxi(get_max(x->lchild, l, r), get_max(x->rchild, l, r));
}
node* build_tree(long long int left, long long int right, long long int* a)
{
	long long int mid;
	node *y = new node;
	node *z = new node;
	node *x = new node;
	if(left == right)
	{
		x = new_node(left, right, a[left]);
		return x;
	}
	else
	{
		x->lind = left;
		x->rind = right;
		mid = left + (right-left)/2;
		y = build_tree(left, mid, a);
		z = build_tree(mid+1, right, a);
		x->val = mxi(y->val, z->val);
		x->lchild = y;
		x->rchild = z;
		return x;
	}
}
node* update(node* root, long long int index, long long int data)
{
	if(root->lind > index || root->rind < index)
		return root;
	if(root->lind == root->rind)
	{
		if(root->lind == index)
			root->val = data;
		return root;
	}
	root->lchild = update(root->lchild, index, data);
	root->rchild = update(root->rchild, index, data);
	root->val = mxi(root->lchild->val, root->rchild->val);
	return root;
}
int main()
{
	long long int n, i, x, y;
	vector <pair<long long int, long long int> > vec;
	cin >> n;
	long long int a[n], b[n], v[n];
	for(i=0; i<n; i++)
	{
		cin >> x >> y;
		v[i] = x*x*y;
		vec.push_back(make_pair(v[i], i));
	}
	sort(vec.begin(), vec.end());
	for(i=0; i<n; i++)
	{
		b[vec[i].second] = i;
	}
	for(i=0; i<n; i++)
		a[i] = 0;
	node* root = build_tree(0, n-1, a);
	for(i=0; i<n; i++)
	{
		root = update(root, b[i], get_max(root, 0, b[i]-1) + v[i]);
	}
	cout << setprecision(15) << 3.14159265358979*(double)root->val;
}


#include <bits/stdc++.h>

using namespace std;

long long int mxi(long long int a, long long int b)
{
	return a>b?a:b;
}
long long int arr[300000]={0};
long long int tree[300000];

/**
 * Build and init tree
 */
void build_tree(long long int node, long long int a, long long int b) {
    if(a > b) return; // Out of range

  	if(a == b) { // Leaf node
    		tree[node] = arr[a]; // Init value
		return;
	}

	build_tree(node*2, a, (a+b)/2); // Init left child
	build_tree(node*2+1, 1+(a+b)/2, b); // Init right child

	tree[node] = mxi(tree[node*2], tree[node*2+1]); // Init root value
}

/**
 * Replacing elements within range [i, j] with value value
 */
void update_tree(long long int node,long long int a, long long int b, long long int i, long long int j, long long int value) {

	if(a > b || a > j || b < i) // Current segment is not within range [i, j]
		return;

  	if(a == b) { // Leaf node
    		tree[node] += value;
    		return;
	}

	update_tree(node*2, a, (a+b)/2, i, j, value); // Updating left child
	update_tree(1+node*2, 1+(a+b)/2, b, i, j, value); // Updating right child

	tree[node] = mxi(tree[node*2], tree[node*2+1]); // Updating root with max value
}

/**
 * Query tree to get max element value within range [i, j]
 */
long long int query_tree(long long int node, long long int a, long long int b, long long int i, long long int j) {

	if(a > b || a > j || b < i) return 0; // Out of range

	if(a >= i && b <= j) // Current segment is totally within range [i, j]
		return tree[node];

	long long int q1 = query_tree(node*2, a, (a+b)/2, i, j); // Query left child
	long long int q2 = query_tree(1+node*2, 1+(a+b)/2, b, i, j); // Query right child

	long long int res = mxi(q1, q2); // Return final result

	return res;
}
int main()
{
	long long int n, i, x, y;
	const long double PI = acos(-1.0);
	vector <pair<long long int, long long int> > vec;
	cin >> n;
	long long int b[n], v[n];
	struct node* root;
	for(i=0; i<n; i++)
	{
		cin >> x >> y;
		v[i] = x*x*y;
		vec.push_back(make_pair(v[i], i));
	}
	sort(vec.begin(), vec.end());
	for(i=0; i<n; i++)
	{
		b[vec[i].second] = i;
	}
	build_tree(1, 0, n-1);
	for(i=0; i<n; i++)
		update_tree(1, 0, n-1, b[i], b[i], query_tree(1, 0, n-1, 0, b[i]-1)+v[i]);
	cout << fixed << setprecision(9);
	cout << PI*query_tree(1, 0, n-1, 0, n-1) << endl;
	return 0;
}


using namespace std;
#include <iostream>
#include <iomanip>
#include <vector>
#include <cstdio>
#include <set>
#include <cctype>
#include <map>
#include <cmath>
#include <queue>
#include <algorithm>
#include <stack>
#include <cctype>
#include <cstring>
#include <string>

#define MAX 100100
#define MOD 1000000007
#define PI 3.1415926535897932384
#define F first
#define S second
#define pb push_back
#define mp make_pair
typedef long long ll;

struct st{
     int s, e;
     ll val;
};

st t[4*MAX];

void build(int s, int e, int pos){
     t[pos].s = s; t[pos].e = e;
     t[pos].val = 0;

     if(e > s){
          int mid = s+(e-s)/2;

          build(s, mid, 2*pos);
          build(mid+1, e, 2*pos+1);
     }
}

ll update(int ind, ll val, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;
     ll aux;

     if(t[pos].s == t[pos].e){
          return t[pos].val = val;
     }

     if(ind <= mid) aux = update(ind, val, 2*pos);
     else aux = update(ind, val, 2*pos+1);

     if(aux > t[pos].val) t[pos].val = aux;
     return t[pos].val;
}

ll query(int s, int e, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;

     if(t[pos].s == s && t[pos].e == e) return t[pos].val;

     if(e <= mid) return query(s, e, 2*pos);
     else if(s > mid) return query(s, e, 2*pos+1);
     ll a1, a2;

     a1 = query(s, mid, 2*pos);
     a2 = query(mid+1, e, 2*pos+1);

     if(a1 > a2) return a1;
     return a2;
}

int n;
vector<pair<ll, int> > temp, vet;

int main(){
     //freopen("in", "r", stdin);
     //freopen("out", "w", stdout);

     cout << setprecision(13);
     cout << fixed;

     cin >> n;

     ll aux, a, b;
     for(int i = 0;i < n;i++){
          cin >> a >> b;
          aux = a*a*b;

          temp.pb(mp(aux, i));
     }

     sort(temp.begin(), temp.end());

     for(int j, i = 0;i < temp.size();i++){
          int ind = 0;
          for(j = i;j < temp.size();j++){
               if(temp[i].F != temp[j].F) break;
               ind = max(ind, temp[i].S);
          }
          i = j-1;

          vet.pb(mp(temp[i].F, ind));
     }

     build(0, n-1, 1);

     int prev = -1; ll val = 0;
     for(int i = 0;i < vet.size();i++){
          aux = 0;
          if(vet[i].S) aux = query(0, vet[i].S-1, 1);
          if(val == vet[i].F && prev < i) aux -= vet[i].F;
          update(vet[i].S, aux+vet[i].F, 1);

          if(val != vet[i].F) prev = vet[i].S;
          else prev = min(prev, vet[i].S);
          val = vet[i].F;
     }

     cout << (query(0, n-1, 1)*1.0)*PI << endl;

     return 0;
}


using namespace std;
#include <iostream>
#include <iomanip>
#include <vector>
#include <cstdio>
#include <set>
#include <cctype>
#include <map>
#include <cmath>
#include <queue>
#include <algorithm>
#include <stack>
#include <cctype>
#include <cstring>
#include <string>

#define MAX 100100
#define MOD 1000000007
#define PI 3.1415926535897932384
#define F first
#define S second
#define pb push_back
#define mp make_pair
typedef long long ll;

struct st{
     int s, e;
     ll val;
};

st t[4*MAX];

void build(int s, int e, int pos){
     t[pos].s = s; t[pos].e = e;
     t[pos].val = 0;

     if(e > s){
          int mid = s+(e-s)/2;

          build(s, mid, 2*pos);
          build(mid+1, e, 2*pos+1);
     }
}

ll update(int ind, ll val, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;
     ll aux;

     if(t[pos].s == t[pos].e){
          return t[pos].val = val;
     }

     if(ind <= mid) aux = update(ind, val, 2*pos);
     else aux = update(ind, val, 2*pos+1);

     if(aux > t[pos].val) t[pos].val = aux;
     return t[pos].val;
}

ll query(int s, int e, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;

     if(t[pos].s == s && t[pos].e == e) return t[pos].val;

     if(e <= mid) return query(s, e, 2*pos);
     else if(s > mid) return query(s, e, 2*pos+1);
     ll a1, a2;

     a1 = query(s, mid, 2*pos);
     a2 = query(mid+1, e, 2*pos+1);

     if(a1 > a2) return a1;
     return a2;
}

int n;
vector<pair<ll, int> > vet;

int main(){
     //freopen("in", "r", stdin);
     //freopen("out", "w", stdout);

     cout << setprecision(13);
     cout << fixed;

     cin >> n;

     ll aux, a, b;
     for(int i = 0;i < n;i++){
          cin >> a >> b;
          aux = a*a*b;

          vet.pb(mp(aux, i));
     }

     build(0, n-1, 1);
     sort(vet.begin(), vet.end());

     int prev = -1; ll val = 0;
     for(int i = 0;i < vet.size();i++){
          aux = 0;
          if(vet[i].S) aux = query(0, vet[i].S-1, 1);
          if(val == vet[i].F && prev < i) aux -= vet[i].F;
          update(vet[i].S, aux+vet[i].F, 1);

          if(val != vet[i].F) prev = i;
          val = vet[i].F;
     }

     cout << (query(0, n-1, 1)*1.0)*PI << endl;

     return 0;
}


using namespace std;
#include <iostream>
#include <iomanip>
#include <vector>
#include <cstdio>
#include <set>
#include <cctype>
#include <map>
#include <cmath>
#include <queue>
#include <algorithm>
#include <stack>
#include <cctype>
#include <cstring>
#include <string>

#define MAX 100100
#define MOD 1000000007
#define PI 3.1415926535897932384
#define F first
#define S second
#define pb push_back
#define mp make_pair
typedef long long ll;

struct st{
     int s, e;
     ll val, ladd;
};

st t[4*MAX];

void build(int s, int e, int pos){
     t[pos].s = s; t[pos].e = e;
     t[pos].val = 0; t[pos].ladd = -1;

     if(e > s){
          int mid = s+(e-s)/2;

          build(s, mid, 2*pos);
          build(mid+1, e, 2*pos+1);
     }
}

pair<ll, ll> update(int ind, ll val, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;
     pair<ll, ll> aux;

     if(t[pos].s == t[pos].e){
          t[pos].val = val;
          t[pos].ladd = val;
          return mp(val, val);
     }

     if(ind <= mid) aux = update(ind, val, 2*pos);
     else aux = update(ind, val, 2*pos+1);

     if(aux.F > t[pos].val){ t[pos].val = aux.F; t[pos].ladd = aux.S; }
     return mp(t[pos].val, t[pos].ladd);
}

ll query(int s, int e, ll ladd, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;

     if(t[pos].s == s && t[pos].e == e){
          if(ladd != t[pos].ladd) return t[pos].val;
          if(s == e) return 0;
     }

     if(e <= mid) return query(s, e, ladd, 2*pos);
     else if(s > mid) return query(s, e, ladd, 2*pos+1);
     ll a1, a2;

     a1 = query(s, mid, ladd, 2*pos);
     a2 = query(mid+1, e, ladd, 2*pos+1);

     if(a1 > a2) return a1;
     return a2;
}

int n;
vector<pair<ll, int> > vet;

int main(){
     //freopen("in", "r", stdin);
     //freopen("out", "w", stdout);

     cout << setprecision(13);
     cout << fixed;

     cin >> n;

     ll aux, a, b;
     for(int i = 0;i < n;i++){
          cin >> a >> b;
          aux = a*a*b;

          vet.pb(mp(aux, i));
     }

     build(0, n-1, 1);
     sort(vet.begin(), vet.end());

     ll val = -10;
     for(int i = 0;i < vet.size();i++){
          aux = 0;
          if(vet[i].F != val) val = -10;
          if(vet[i].S) aux = query(0, vet[i].S-1, val, 1);
          update(vet[i].S, aux+vet[i].F, 1);
          val = vet[i].F;
     }

     cout << (query(0, n-1, -10, 1)*1.0)*PI << endl;

     return 0;
}


using namespace std;
#include <iostream>
#include <iomanip>
#include <vector>
#include <cstdio>
#include <set>
#include <cctype>
#include <map>
#include <cmath>
#include <queue>
#include <algorithm>
#include <stack>
#include <cctype>
#include <cstring>
#include <string>

#define MAX 100100
#define MOD 1000000007
#define PI 3.1415926535897932384
#define F first
#define S second
#define pb push_back
#define mp make_pair
typedef long long ll;

struct st{
     int s, e;
     ll val;
};

st t[4*MAX];

void build(int s, int e, int pos){
     t[pos].s = s; t[pos].e = e;
     t[pos].val = 0.0;

     if(e > s){
          int mid = s+(e-s)/2;

          build(s, mid, 2*pos);
          build(mid+1, e, 2*pos+1);
     }
}

ll update(int ind, double val, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;
     double aux;

     if(t[pos].s == t[pos].e){
          return t[pos].val = val;
     }

     if(ind <= mid) aux = update(ind, val, 2*pos);
     else aux = update(ind, val, 2*pos+1);

     if(aux > t[pos].val) t[pos].val = aux;
     return t[pos].val;
}

ll query(int s, int e, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;

     if(t[pos].s == s && t[pos].e == e) return t[pos].val;

     if(e <= mid) return query(s, e, 2*pos);
     else if(s > mid) return query(s, e, 2*pos+1);
     double a1, a2;

     a1 = query(s, mid, 2*pos);
     a2 = query(mid+1, e, 2*pos+1);

     if(a1 > a2) return a1;
     return a2;
}

int n;
vector<pair<ll, int> > vet;

int main(){
     //freopen("in", "r", stdin);
     //freopen("out", "w", stdout);

     cout << setprecision(10);
     cout << fixed;

     cin >> n;
     ll aux, a, b;

     for(int i = 0;i < n;i++){
          scanf("%I64d %I64d", &a, &b);
          aux = a*a*b;

          vet.pb(mp(aux, i));
     }

     build(0, n-1, 1);
     sort(vet.begin(), vet.end());

     aux = 0;
     for(int i = 0;i < vet.size();i++){
          if(vet[i].S) aux = query(0, vet[i].S-1, 1);
          update(vet[i].S, aux+vet[i].F, 1);
     }

     cout << (query(0, n-1, 1)*1.0)*PI << endl;

     return 0;
}


using namespace std;
#include <iostream>
#include <iomanip>
#include <vector>
#include <cstdio>
#include <set>
#include <cctype>
#include <map>
#include <cmath>
#include <queue>
#include <algorithm>
#include <stack>
#include <cctype>
#include <cstring>
#include <string>

#define MAX 100100
#define MOD 1000000007
#define PI 3.1415926535897932384
#define F first
#define S second
#define pb push_back
#define mp make_pair
typedef long long ll;

struct st{
     int s, e;
     ll val;
};

st t[4*MAX];

void build(int s, int e, int pos){
     t[pos].s = s; t[pos].e = e;
     t[pos].val = 0;

     if(e > s){
          int mid = s+(e-s)/2;

          build(s, mid, 2*pos);
          build(mid+1, e, 2*pos+1);
     }
}

ll update(int ind, ll val, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;
     ll aux;

     if(t[pos].s == t[pos].e){
          return t[pos].val = val;
     }

     if(ind <= mid) aux = update(ind, val, 2*pos);
     else aux = update(ind, val, 2*pos+1);

     if(aux > t[pos].val) t[pos].val = aux;
     return t[pos].val;
}

ll query(int s, int e, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;

     if(t[pos].s == s && t[pos].e == e) return t[pos].val;

     if(e <= mid) return query(s, e, 2*pos);
     else if(s > mid) return query(s, e, 2*pos+1);
     ll a1, a2;

     a1 = query(s, mid, 2*pos);
     a2 = query(mid+1, e, 2*pos+1);

     if(a1 > a2) return a1;
     return a2;
}

int n;
vector<pair<ll, int> > vet;

int main(){
     //freopen("in", "r", stdin);
     //freopen("out", "w", stdout);

     cout << setprecision(13);
     cout << fixed;

     cin >> n;

     ll aux, a, b;
     for(int i = 0;i < n;i++){
          cin >> a >> b;
          aux = a*a*b;

          vet.pb(mp(aux, i));
     }

     build(0, n-1, 1);
     sort(vet.begin(), vet.end());

     for(int i = 0;i < vet.size();i++){
          int j, maxi = vet[i].S;
          for(j = i+1;j < vet.size();j++){
               if(vet[j].F != vet[i].F) break;
               maxi = max(maxi, vet[j].S);
          }

          for(int l = i;l < j;l++) vet[l].S = maxi;
     }

     for(int i = 0;i < vet.size();i++){
          aux = 0;
          if(vet[i].S) aux = query(0, vet[i].S-1, 1);
          update(vet[i].S, aux+vet[i].F, 1);
     }

     cout << (query(0, n-1, 1)*1.0)*PI << endl;

     return 0;
}


using namespace std;
#include <iostream>
#include <iomanip>
#include <vector>
#include <cstdio>
#include <set>
#include <cctype>
#include <map>
#include <cmath>
#include <queue>
#include <algorithm>
#include <stack>
#include <cctype>
#include <cstring>
#include <string>

#define MAX 100100
#define MOD 1000000007
#define PI 3.1415926535897932384
#define F first
#define S second
#define pb push_back
#define mp make_pair
typedef long long ll;

struct st{
     int s, e;
     ll val;
};

st t[4*MAX];

void build(int s, int e, int pos){
     t[pos].s = s; t[pos].e = e;
     t[pos].val = 0;

     if(e > s){
          int mid = s+(e-s)/2;

          build(s, mid, 2*pos);
          build(mid+1, e, 2*pos+1);
     }
}

ll update(int ind, ll val, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;
     ll aux;

     if(t[pos].s == t[pos].e){
          return t[pos].val = val;
     }

     if(ind <= mid) aux = update(ind, val, 2*pos);
     else aux = update(ind, val, 2*pos+1);

     if(aux > t[pos].val) t[pos].val = aux;
     return t[pos].val;
}

ll query(int s, int e, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;

     if(t[pos].s == s && t[pos].e == e) return t[pos].val;

     if(e <= mid) return query(s, e, 2*pos);
     else if(s > mid) return query(s, e, 2*pos+1);
     ll a1, a2;

     a1 = query(s, mid, 2*pos);
     a2 = query(mid+1, e, 2*pos+1);

     if(a1 > a2) return a1;
     return a2;
}

int n;
vector<pair<ll, int> > temp, vet;

int main(){
     //freopen("in", "r", stdin);
     //freopen("out", "w", stdout);

     cout << setprecision(13);
     cout << fixed;

     cin >> n;

     ll aux, a, b;
     for(int i = 0;i < n;i++){
          cin >> a >> b;
          aux = a*a*b;

          temp.pb(mp(aux, i));
     }

     sort(temp.begin(), temp.end());

     for(int j, i = 0;i < temp.size();i++){
          int ind = 0;
          for(j = i;j < temp.size();j++){
               if(temp[i].F != temp[j].F) break;
               ind = max(ind, temp[i].S);
          }
          i = j-1;

          vet.pb(mp(temp[i].F, ind));
     }

     build(0, n-1, 1);

     for(int i = 0;i < vet.size();i++){
          aux = 0;
          if(vet[i].S) aux = query(0, vet[i].S-1, 1);
          update(vet[i].S, aux+vet[i].F, 1);
     }

     cout << (query(0, n-1, 1)*1.0)*PI << endl;

     return 0;
}


using namespace std;
#include <iostream>
#include <iomanip>
#include <vector>
#include <cstdio>
#include <set>
#include <cctype>
#include <map>
#include <cmath>
#include <queue>
#include <algorithm>
#include <stack>
#include <cctype>
#include <cstring>
#include <string>

#define MAX 100100
#define MOD 1000000007
#define PI 3.1415926535897932384
#define F first
#define S second
#define pb push_back
#define mp make_pair
typedef long long ll;

struct st{
     int s, e;
     ll val;
};

st t[4*MAX];

void build(int s, int e, int pos){
     t[pos].s = s; t[pos].e = e;
     t[pos].val = 0.0;

     if(e > s){
          int mid = s+(e-s)/2;

          build(s, mid, 2*pos);
          build(mid+1, e, 2*pos+1);
     }
}

ll update(int ind, double val, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;
     ll aux;

     if(t[pos].s == t[pos].e){
          return t[pos].val = val;
     }

     if(ind <= mid) aux = update(ind, val, 2*pos);
     else aux = update(ind, val, 2*pos+1);

     if(aux > t[pos].val) t[pos].val = aux;
     return t[pos].val;
}

ll query(int s, int e, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;

     if(t[pos].s == s && t[pos].e == e) return t[pos].val;

     if(e <= mid) return query(s, e, 2*pos);
     else if(s > mid) return query(s, e, 2*pos+1);
     ll a1, a2;

     a1 = query(s, mid, 2*pos);
     a2 = query(mid+1, e, 2*pos+1);

     if(a1 > a2) return a1;
     return a2;
}

int n;
vector<pair<ll, int> > vet;

int main(){
     //freopen("in", "r", stdin);
     //freopen("out", "w", stdout);

     cout << setprecision(10);
     cout << fixed;

     cin >> n;
     ll aux, a, b;

     for(int i = 0;i < n;i++){
          scanf("%I64d %I64d", &a, &b);
          aux = a*a*b;

          vet.pb(mp(aux, i));
     }

     build(0, n-1, 1);
     sort(vet.begin(), vet.end());

     aux = 0;
     for(int i = 0;i < vet.size();i++){
          if(vet[i].S) aux = query(0, vet[i].S-1, 1);
          update(vet[i].S, aux+vet[i].F, 1);
     }

     cout << (query(0, n-1, 1)*1.0)*PI << endl;

     return 0;
}


using namespace std;
#include <iostream>
#include <iomanip>
#include <vector>
#include <cstdio>
#include <set>
#include <cctype>
#include <map>
#include <cmath>
#include <queue>
#include <algorithm>
#include <stack>
#include <cctype>
#include <cstring>
#include <string>

#define MAX 100100
#define MOD 1000000007
#define PI 3.1415926535897932384
#define F first
#define S second
#define pb push_back
#define mp make_pair
typedef long long ll;

struct st{
     int s, e;
     ll val;
};

st t[4*MAX];

void build(int s, int e, int pos){
     t[pos].s = s; t[pos].e = e;
     t[pos].val = 0;

     if(e > s){
          int mid = s+(e-s)/2;

          build(s, mid, 2*pos);
          build(mid+1, e, 2*pos+1);
     }
}

ll update(int ind, ll val, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;
     ll aux;

     if(t[pos].s == t[pos].e){
          return t[pos].val = val;
     }

     if(ind <= mid) aux = update(ind, val, 2*pos);
     else aux = update(ind, val, 2*pos+1);

     if(aux > t[pos].val) t[pos].val = aux;
     return t[pos].val;
}

ll query(int s, int e, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;

     if(t[pos].s == s && t[pos].e == e) return t[pos].val;

     if(e <= mid) return query(s, e, 2*pos);
     else if(s > mid) return query(s, e, 2*pos+1);
     ll a1, a2;

     a1 = query(s, mid, 2*pos);
     a2 = query(mid+1, e, 2*pos+1);

     if(a1 > a2) return a1;
     return a2;
}

int n;
vector<pair<ll, int> > vet;

int main(){
     //freopen("in", "r", stdin);
     //freopen("out", "w", stdout);

     cout << setprecision(13);
     cout << fixed;

     cin >> n;
     ll aux, a, b;

     for(int i = 0;i < n;i++){
          scanf("%I64d %I64d", &a, &b);
          aux = a*a*b;

          vet.pb(mp(aux, i));
     }

     build(0, n-1, 1);
     sort(vet.begin(), vet.end());

     aux = 0;
     for(int i = 0;i < vet.size();i++){
          if(vet[i].S) aux = query(0, vet[i].S-1, 1);
          update(vet[i].S, aux+vet[i].F, 1);
     }

     aux = query(0, n-1, 1);
     double res = (aux*1.0)*PI;
     cout << res << endl;

     return 0;
}


using namespace std;
#include <iostream>
#include <iomanip>
#include <vector>
#include <cstdio>
#include <set>
#include <cctype>
#include <map>
#include <cmath>
#include <queue>
#include <algorithm>
#include <stack>
#include <cctype>
#include <cstring>
#include <string>

#define MAX 100100
#define MOD 1000000007
#define PI 3.1415926535897932384
#define F first
#define S second
#define pb push_back
#define mp make_pair
typedef long long ll;

struct st{
     int s, e;
     ll val;
};

st t[4*MAX];

void build(int s, int e, int pos){
     t[pos].s = s; t[pos].e = e;
     t[pos].val = 0;

     if(e > s){
          int mid = s+(e-s)/2;

          build(s, mid, 2*pos);
          build(mid+1, e, 2*pos+1);
     }
}

ll update(int ind, ll val, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;
     ll aux;

     if(t[pos].s == t[pos].e){
          return t[pos].val = val;
     }

     if(ind <= mid) aux = update(ind, val, 2*pos);
     else aux = update(ind, val, 2*pos+1);

     if(aux > t[pos].val) t[pos].val = aux;
     return t[pos].val;
}

ll query(int s, int e, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;

     if(t[pos].s == s && t[pos].e == e) return t[pos].val;

     if(e <= mid) return query(s, e, 2*pos);
     else if(s > mid) return query(s, e, 2*pos+1);
     ll a1, a2;

     a1 = query(s, mid, 2*pos);
     a2 = query(mid+1, e, 2*pos+1);

     if(a1 > a2) return a1;
     return a2;
}

int n;
vector<pair<ll, int> > vet;

int main(){
     //freopen("in", "r", stdin);
     //freopen("out", "w", stdout);

     cout << setprecision(10);
     cout << fixed;

     cin >> n;
     ll aux, a, b;

     for(int i = 0;i < n;i++){
          scanf("%I64d %I64d", &a, &b);
          aux = a*a*b;

          vet.pb(mp(aux, i));
     }

     build(0, n-1, 1);
     sort(vet.begin(), vet.end());

     aux = 0;
     for(int i = 0;i < vet.size();i++){
          if(vet[i].S) aux = query(0, vet[i].S-1, 1);
          update(vet[i].S, aux+vet[i].F, 1);
     }

     cout << (query(0, n-1, 1)*1.0)*PI << endl;

     return 0;
}


using namespace std;
#include <iostream>
#include <iomanip>
#include <vector>
#include <cstdio>
#include <set>
#include <cctype>
#include <map>
#include <cmath>
#include <queue>
#include <algorithm>
#include <stack>
#include <cctype>
#include <cstring>
#include <string>

#define MAX 100100
#define MOD 1000000007
#define PI 3.1415926535897932384
#define F first
#define S second
#define pb push_back
#define mp make_pair
typedef long long ll;

struct st{
     int s, e;
     ll val;
};

st t[4*MAX];

void build(int s, int e, int pos){
     t[pos].s = s; t[pos].e = e;
     t[pos].val = 0;

     if(e > s){
          int mid = s+(e-s)/2;

          build(s, mid, 2*pos);
          build(mid+1, e, 2*pos+1);
     }
}

ll update(int ind, ll val, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;
     ll aux;

     if(t[pos].s == t[pos].e){
          return t[pos].val = val;
     }

     if(ind <= mid) aux = update(ind, val, 2*pos);
     else aux = update(ind, val, 2*pos+1);

     if(aux > t[pos].val) t[pos].val = aux;
     return t[pos].val;
}

ll query(int s, int e, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;

     if(t[pos].s == s && t[pos].e == e) return t[pos].val;

     if(e <= mid) return query(s, e, 2*pos);
     else if(s > mid) return query(s, e, 2*pos+1);
     ll a1, a2;

     a1 = query(s, mid, 2*pos);
     a2 = query(mid+1, e, 2*pos+1);

     if(a1 > a2) return a1;
     return a2;
}

int n;
vector<pair<ll, int> > vet;

int main(){
     //freopen("in", "r", stdin);
     //freopen("out", "w", stdout);

     cout << setprecision(13);
     cout << fixed;

     cin >> n;

     ll aux, a, b;
     for(int i = 0;i < n;i++){
          cin >> a >> b;
          aux = a*a*b;

          vet.pb(mp(aux, i));
     }

     build(0, n-1, 1);
     sort(vet.begin(), vet.end());

     int prev = -1; ll val = 0;
     for(int i = 0;i < vet.size();i++){
          aux = 0;
          if(vet[i].S) aux = query(0, vet[i].S-1, 1);
          if(val == vet[i].F && prev < i) aux -= vet[i].F;
          update(vet[i].S, aux+vet[i].F, 1);

          if(val != vet[i].F) prev = vet[i].S;
          else prev = min(prev, vet[i].S);
          val = vet[i].F;
     }

     cout << (query(0, n-1, 1)*1.0)*PI << endl;

     return 0;
}


using namespace std;
#include <iostream>
#include <iomanip>
#include <vector>
#include <cstdio>
#include <set>
#include <cctype>
#include <map>
#include <cmath>
#include <queue>
#include <algorithm>
#include <stack>
#include <cctype>
#include <cstring>
#include <string>

#define MAX 100100
#define MOD 1000000007
#define PI 3.1415926535897932384
#define F first
#define S second
#define pb push_back
#define mp make_pair
typedef long long ll;

struct st{
     int s, e;
     ll val, ladd;
};

st t[4*MAX];

void build(int s, int e, int pos){
     t[pos].s = s; t[pos].e = e;
     t[pos].val = 0; t[pos].ladd = -1;

     if(e > s){
          int mid = s+(e-s)/2;

          build(s, mid, 2*pos);
          build(mid+1, e, 2*pos+1);
     }
}

pair<ll, ll> update(int ind, ll val, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;
     pair<ll, ll> aux;

     if(t[pos].s == t[pos].e){
          t[pos].val = val;
          t[pos].ladd = val;
          return mp(val, val);
     }

     if(ind <= mid) aux = update(ind, val, 2*pos);
     else aux = update(ind, val, 2*pos+1);

     if(aux.F > t[pos].val){ t[pos].val = aux.F; t[pos].ladd = aux.S; }
     return mp(t[pos].val, t[pos].ladd);
}

ll query(int s, int e, ll ladd, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;

     if(t[pos].s == s && t[pos].e == e){
          if(ladd != t[pos].ladd) return t[pos].val;
          if(s == e) return 0;
     }

     if(e <= mid) return query(s, e, ladd, 2*pos);
     else if(s > mid) return query(s, e, ladd, 2*pos+1);
     ll a1, a2;

     a1 = query(s, mid, ladd, 2*pos);
     a2 = query(mid+1, e, ladd, 2*pos+1);

     if(a1 > a2) return a1;
     return a2;
}

int n;
vector<pair<ll, int> > vet;

int main(){
     //freopen("in", "r", stdin);
     //freopen("out", "w", stdout);

     cout << setprecision(13);
     cout << fixed;

     cin >> n;

     ll aux, a, b;
     for(int i = 0;i < n;i++){
          cin >> a >> b;
          aux = a*a*b;

          vet.pb(mp(aux, i));
     }

     build(0, n-1, 1);
     sort(vet.begin(), vet.end());

     ll val = -10;
     for(int i = 0;i < vet.size();i++){
          aux = 0;
          if(vet[i].S) aux = query(0, vet[i].S-1, val, 1);
          update(vet[i].S, aux+vet[i].F, 1);
          val = vet[i].F;
     }

     cout << (query(0, n-1, -10, 1)*1.0)*PI << endl;

     return 0;
}


using namespace std;
#include <iostream>
#include <iomanip>
#include <vector>
#include <cstdio>
#include <set>
#include <cctype>
#include <map>
#include <cmath>
#include <queue>
#include <algorithm>
#include <stack>
#include <cctype>
#include <cstring>
#include <string>

#define MAX 100100
#define MOD 1000000007
#define PI 3.1415926535897932384
#define F first
#define S second
#define pb push_back
#define mp make_pair
typedef long long ll;

struct st{
     int s, e;
     ll val;
};

st t[4*MAX];

void build(int s, int e, int pos){
     t[pos].s = s; t[pos].e = e;
     t[pos].val = 0;

     if(e > s){
          int mid = s+(e-s)/2;

          build(s, mid, 2*pos);
          build(mid+1, e, 2*pos+1);
     }
}

ll update(int ind, ll val, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;
     ll aux;

     if(t[pos].s == t[pos].e){
          return t[pos].val = val;
     }

     if(ind <= mid) aux = update(ind, val, 2*pos);
     else aux = update(ind, val, 2*pos+1);

     if(aux > t[pos].val) t[pos].val = aux;
     return t[pos].val;
}

ll query(int s, int e, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;

     if(t[pos].s == s && t[pos].e == e) return t[pos].val;

     if(e <= mid) return query(s, e, 2*pos);
     else if(s > mid) return query(s, e, 2*pos+1);
     ll a1, a2;

     a1 = query(s, mid, 2*pos);
     a2 = query(mid+1, e, 2*pos+1);

     if(a1 > a2) return a1;
     return a2;
}

int n;
vector<pair<ll, int> > vet;

int main(){
     //freopen("in", "r", stdin);
     //freopen("out", "w", stdout);

     cout << setprecision(13);
     cout << fixed;

     cin >> n;

     ll aux, a, b;
     for(int i = 0;i < n;i++){
          cin >> a >> b;
          aux = a*a*b;

          vet.pb(mp(aux, i));
     }

     build(0, n-1, 1);
     sort(vet.begin(), vet.end());

     for(int i = 0;i < vet.size();i++){
          int j, maxiS = vet[i].S;
          ll maxiF = vet[i].F;
          for(j = i+1;j < vet.size();j++){
               if(vet[j].F != vet[i].F) break;
               maxiS = max(maxiS, vet[j].S);
               if(vet[j].F > maxiF) maxiF = vet[j].F;
          }

          for(int l = i;l < j;l++){ vet[l].S = maxiS; vet[l].F = maxiF; }
     }

     for(int i = 0;i < vet.size();i++){
          aux = 0;
          if(vet[i].S) aux = query(0, vet[i].S-1, 1);
          update(vet[i].S, aux+vet[i].F, 1);
     }

     cout << (query(0, n-1, 1)*1.0)*PI << endl;

     return 0;
}


using namespace std;
#include <iostream>
#include <iomanip>
#include <vector>
#include <cstdio>
#include <set>
#include <cctype>
#include <map>
#include <cmath>
#include <queue>
#include <algorithm>
#include <stack>
#include <cctype>
#include <cstring>
#include <string>

#define MAX 100100
#define MOD 1000000007
#define PI 3.1415926535897932384
#define F first
#define S second
#define pb push_back
#define mp make_pair
typedef long long ll;

struct st{
     int s, e;
     ll val, ladd;
};

st t[4*MAX];

void build(int s, int e, int pos){
     t[pos].s = s; t[pos].e = e;
     t[pos].val = 0; t[pos].ladd = -1;

     if(e > s){
          int mid = s+(e-s)/2;

          build(s, mid, 2*pos);
          build(mid+1, e, 2*pos+1);
     }
}

ll update(int ind, ll val, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;
     ll aux;

     if(t[pos].s == t[pos].e){
          return t[pos].val = val;
     }

     if(ind <= mid) aux = update(ind, val, 2*pos);
     else aux = update(ind, val, 2*pos+1);

     if(aux > t[pos].val) t[pos].val = aux;
     return t[pos].val;
}

ll query(int s, int e, ll ladd, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;

     if(t[pos].s == s && t[pos].e == e){
          if(ladd != t[pos].ladd) return t[pos].val;
          if(s == e) return 0;
     }

     if(e <= mid) return query(s, e, ladd, 2*pos);
     else if(s > mid) return query(s, e, ladd, 2*pos+1);
     ll a1, a2;

     a1 = query(s, mid, ladd, 2*pos);
     a2 = query(mid+1, e, ladd, 2*pos+1);

     if(a1 > a2) return a1;
     return a2;
}

int n;
vector<pair<ll, int> > vet;

int main(){
     //freopen("in", "r", stdin);
     //freopen("out", "w", stdout);

     cout << setprecision(13);
     cout << fixed;

     cin >> n;

     ll aux, a, b;
     for(int i = 0;i < n;i++){
          cin >> a >> b;
          aux = a*a*b;

          vet.pb(mp(aux, i));
     }

     build(0, n-1, 1);
     sort(vet.begin(), vet.end());

     ll val = -10;
     for(int i = 0;i < vet.size();i++){
          aux = 0;
          if(vet[i].S) aux = query(0, vet[i].S-1, val, 1);
          update(vet[i].S, aux+vet[i].F, 1);
          val = vet[i].F;
     }

     cout << (query(0, n-1, -10, 1)*1.0)*PI << endl;

     return 0;
}


using namespace std;
#include <iostream>
#include <iomanip>
#include <vector>
#include <cstdio>
#include <set>
#include <cctype>
#include <map>
#include <cmath>
#include <queue>
#include <algorithm>
#include <stack>
#include <cctype>
#include <cstring>
#include <string>

#define MAX 100100
#define MOD 1000000007
#define PI 3.1415926535897932384
#define F first
#define S second
#define pb push_back
#define mp make_pair
typedef long long ll;

struct st{
     int s, e;
     ll val;
};

st t[4*MAX];

void build(int s, int e, int pos){
     t[pos].s = s; t[pos].e = e;
     t[pos].val = 0;

     if(e > s){
          int mid = s+(e-s)/2;

          build(s, mid, 2*pos);
          build(mid+1, e, 2*pos+1);
     }
}

ll update(int ind, ll val, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;
     ll aux;

     if(t[pos].s == t[pos].e){
          return t[pos].val = val;
     }

     if(ind <= mid) aux = update(ind, val, 2*pos);
     else aux = update(ind, val, 2*pos+1);

     if(aux > t[pos].val) t[pos].val = aux;
     return t[pos].val;
}

ll query(int s, int e, int pos){
     int mid = t[pos].s+(t[pos].e-t[pos].s)/2;

     if(t[pos].s == s && t[pos].e == e) return t[pos].val;

     if(e <= mid) return query(s, e, 2*pos);
     else if(s > mid) return query(s, e, 2*pos+1);
     ll a1, a2;

     a1 = query(s, mid, 2*pos);
     a2 = query(mid+1, e, 2*pos+1);

     if(a1 > a2) return a1;
     return a2;
}

int n;
vector<pair<ll, int> > vet;
queue<pair<ll, int> > uq;

int main(){
     //freopen("in", "r", stdin);
     //freopen("out", "w", stdout);

     cout << setprecision(13);
     cout << fixed;

     cin >> n;

     ll aux, a, b;
     for(int i = 0;i < n;i++){
          cin >> a >> b;
          aux = a*a*b;

          vet.pb(mp(aux, i));
     }

     sort(vet.begin(), vet.end());

     build(0, n-1, 1);

     for(int i = 0;i < vet.size();i++){
          if(i > 0 && vet[i].F != vet[i-1].F){
               while(!uq.empty()){
                    update(uq.front().S, uq.front().F, 1);
                    uq.pop();
               }
          }

          aux = 0;
          if(vet[i].S) aux = query(0, vet[i].S-1, 1);
          uq.push(mp(vet[i].F+aux, vet[i].S));

          if(i == vet.size()-1){
               while(!uq.empty()){
                    update(uq.front().S, uq.front().F, 1);
                    uq.pop();
               }
          }
     }

     cout << (query(0, n-1, 1)*1.0)*PI << endl;

     return 0;
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <random>
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x=(x<<3)+(x<<1)+_-'0');}while(0)
char _;
#define inf (1 << 30)
#define lc(x) (x << 1)
#define rc(x) ((x << 1) | 1)
#define m(a,b) ((a + b) / 2)
#define EPS 1e-6
#define For(a, b, c) for(int a = b; a <= c; a ++)
#define Rev(a, b, c) for(int a = b; a >= c; a --)
#define pb push_back
#define mp make_pair
#define io cin.sync_with_stdio(0); cin.tie(0);
#define MTRAND mt19937 gen(4)
#define RNG(l, h) gen() % (h - l + 1) + l
using namespace std;
const int MAXN =  120005, MOD = 1e9 + 7;
typedef pair<int,int> pii;

int N; long double ans;
long double r[MAXN], h[MAXN];
long double v[MAXN];
long double seg[4 * MAXN], lazy[4 * MAXN];
int pl[MAXN];
vector<long double> order;

long double PI = 3.1415926535897932384;

void push_down(int idx)
{
    seg[lc(idx)] = max(seg[lc(idx)], lazy[idx]);
    seg[rc(idx)] = max(seg[rc(idx)], lazy[idx]);
    lazy[lc(idx)] = max(lazy[lc(idx)], lazy[idx]);
    lazy[rc(idx)] = max(lazy[rc(idx)], lazy[idx]);
}

void push_up(int idx)
{
    seg[idx] = max(seg[lc(idx)], seg[rc(idx)]);
}

void build(int idx, int l, int r)
{
    if (l == r)
    {
        seg[idx] = 0;
        return;
    }
    int mid = m(l, r);
    build(lc(idx), l, mid);
    build(rc(idx), mid + 1, r);
    push_up(idx);
}

long double query(int idx, int tl, int tr, int l, int r)
{
    if (tl == l && tr == r)
        return seg[idx];
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        return query(lc(idx), tl, mid, l, r);
    else if (l > mid)
        return query(rc(idx), mid + 1, tr, l, r);
    else
    {
        return max(query(lc(idx), tl, mid, l, mid),
                   query(rc(idx), mid + 1, tr, mid + 1, r));
    }
}

void update(int idx, int tl, int tr, int l, int r, long double v)
{
    if (tl == l && tr == r)
    {
        seg[idx] = max(seg[idx], v);
        lazy[idx] = max(lazy[idx], v);
        return ;
    }
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        update(lc(idx), tl, mid, l, r, v);
    else if (l > mid)
        update(rc(idx), mid + 1, tr, l, r, v);
    else
    {
        update(lc(idx), tl, mid, l, mid, v);
        update(rc(idx), mid + 1, tr, mid + 1, r, v);
    }
    push_up(idx);
}
int main() { io
    cin >> N;
    For(i, 1, N)
    {
        cin >> r[i] >> h[i];
        v[i] = r[i] * r[i] * h[i] * PI;
        order.push_back(v[i]);
    }
    sort(order.begin(), order.end());

    For(i, 1, N)
    {
        int pos = (int)(lower_bound(order.begin(), order.end(), v[i]) - order.begin());
        pl[i] = pos + 1;
    }
    For(i, 1, N)
    {
        long double best;
        if (pl[i] - 1 == 0)
            best = 0;
        else
            best = query(1, 1, N, 1, pl[i] - 1);
        ans = max(ans, best + v[i]);
        update(1, 1, N, pl[i], N, best + v[i]);
    }
    printf("%.9Lf", ans);
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
#include <iomanip>
#include <set>
#include <queue>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <random>
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x=(x<<3)+(x<<1)+_-'0');}while(0)
char _;
#define inf (1 << 30)
#define lc(x) (x << 1)
#define rc(x) ((x << 1) | 1)
#define m(a,b) ((a + b) / 2)
#define EPS 1e-7
#define For(a, b, c) for(int a = b; a <= c; a ++)
#define Rev(a, b, c) for(int a = b; a >= c; a --)
#define pb push_back
#define mp make_pair
#define io cin.sync_with_stdio(0); cin.tie(0);
#define MTRAND mt19937 gen(4)
#define RNG(l, h) gen() % (h - l + 1) + l
using namespace std;
const int MAXN =  120005;
typedef pair<int,int> pii;

int N; long long ans;
int r[MAXN], h[MAXN];
long long v[MAXN];
long double seg[4 * MAXN], lazy[4 * MAXN];
int pl[MAXN];
vector<long long> order;

long double PI = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196;

void push_down(int idx)
{
    seg[lc(idx)] = max(seg[lc(idx)], lazy[idx]);
    seg[rc(idx)] = max(seg[rc(idx)], lazy[idx]);
    lazy[lc(idx)] = max(lazy[lc(idx)], lazy[idx]);
    lazy[rc(idx)] = max(lazy[rc(idx)], lazy[idx]);
}

void push_up(int idx)
{
    seg[idx] = max(seg[lc(idx)], seg[rc(idx)]);
}

void build(int idx, int l, int r)
{
    if (l == r)
    {
        seg[idx] = 0;
        return;
    }
    int mid = m(l, r);
    build(lc(idx), l, mid);
    build(rc(idx), mid + 1, r);
    push_up(idx);
}

long double query(int idx, int tl, int tr, int l, int r)
{
    if (tl == l && tr == r)
        return seg[idx];
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        return query(lc(idx), tl, mid, l, r);
    else if (l > mid)
        return query(rc(idx), mid + 1, tr, l, r);
    else
    {
        return max(query(lc(idx), tl, mid, l, mid),
                   query(rc(idx), mid + 1, tr, mid + 1, r));
    }
}

void update(int idx, int tl, int tr, int l, int r, long double v)
{
    if (tl == l && tr == r)
    {
        seg[idx] = max(seg[idx], v);
        lazy[idx] = max(lazy[idx], v);
        return ;
    }
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        update(lc(idx), tl, mid, l, r, v);
    else if (l > mid)
        update(rc(idx), mid + 1, tr, l, r, v);
    else
    {
        update(lc(idx), tl, mid, l, mid, v);
        update(rc(idx), mid + 1, tr, mid + 1, r, v);
    }
    push_up(idx);
}
int main() { io
    cin >> N;
    For(i, 1, N)
    {
        cin >> r[i] >> h[i];
        v[i] = (long double) r[i] * r[i] * h[i];
        order.push_back((long long)r[i] * r[i] * h[i]);
    }
    sort(order.begin(), order.end());
    For(i, 1, N)
    {
        int pos = (int)(lower_bound(order.begin(), order.end(), (long long) (r[i] * r[i] * h[i])) - order.begin());
        pl[i] = pos + 1;
    }
    For(i, 1, N)
    {
        long long best;
        if (pl[i] - 1 == 0)
            best = 0;
        else
            best = query(1, 1, N, 1, pl[i] - 1);
        ans = max(ans, best + v[i]);
        update(1, 1, N, pl[i], N, best + v[i]);
    }
    cout << setprecision(20) << (long double) ans * 4 * atan(1) << endl;
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <random>
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x=(x<<3)+(x<<1)+_-'0');}while(0)
char _;
#define inf (1 << 30)
#define lc(x) (x << 1)
#define rc(x) ((x << 1) | 1)
#define m(a,b) ((a + b) / 2)
#define EPS 1e-6
#define For(a, b, c) for(int a = b; a <= c; a ++)
#define Rev(a, b, c) for(int a = b; a >= c; a --)
#define pb push_back
#define mp make_pair
#define io cin.sync_with_stdio(0); cin.tie(0);
#define MTRAND mt19937 gen(4)
#define RNG(l, h) gen() % (h - l + 1) + l
using namespace std;
const int MAXN =  120005, MOD = 1e9 + 7;
typedef pair<int,int> pii;

int N; long double ans;
int r[MAXN], h[MAXN];
long double v[MAXN];
long double seg[4 * MAXN], lazy[4 * MAXN];
int pl[MAXN];
vector<long long> order;

long double PI = 3.14159265358979323846264338328;

void push_down(int idx)
{
    seg[lc(idx)] = max(seg[lc(idx)], lazy[idx]);
    seg[rc(idx)] = max(seg[rc(idx)], lazy[idx]);
    lazy[lc(idx)] = max(lazy[lc(idx)], lazy[idx]);
    lazy[rc(idx)] = max(lazy[rc(idx)], lazy[idx]);
}

void push_up(int idx)
{
    seg[idx] = max(seg[lc(idx)], seg[rc(idx)]);
}

void build(int idx, int l, int r)
{
    if (l == r)
    {
        seg[idx] = 0;
        return;
    }
    int mid = m(l, r);
    build(lc(idx), l, mid);
    build(rc(idx), mid + 1, r);
    push_up(idx);
}

long double query(int idx, int tl, int tr, int l, int r)
{
    if (tl == l && tr == r)
        return seg[idx];
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        return query(lc(idx), tl, mid, l, r);
    else if (l > mid)
        return query(rc(idx), mid + 1, tr, l, r);
    else
    {
        return max(query(lc(idx), tl, mid, l, mid),
                   query(rc(idx), mid + 1, tr, mid + 1, r));
    }
}

void update(int idx, int tl, int tr, int l, int r, long double v)
{
    if (tl == l && tr == r)
    {
        seg[idx] = max(seg[idx], v);
        lazy[idx] = max(lazy[idx], v);
        return ;
    }
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        update(lc(idx), tl, mid, l, r, v);
    else if (l > mid)
        update(rc(idx), mid + 1, tr, l, r, v);
    else
    {
        update(lc(idx), tl, mid, l, mid, v);
        update(rc(idx), mid + 1, tr, mid + 1, r, v);
    }
    push_up(idx);
}
int main() { io
    cin >> N;
    For(i, 1, N)
    {
        cin >> r[i] >> h[i];
        v[i] = (long double) r[i] * r[i] * h[i] * PI;
        order.push_back((long long)r[i] * r[i] * h[i]);
    }
    sort(order.begin(), order.end());

    For(i, 1, N)
    {
        int pos = (int)(lower_bound(order.begin(), order.end(), (long long) (r[i] * r[i] * h[i])) - order.begin());
        pl[i] = pos + 1;
    }
    For(i, 1, N)
    {
        long double best;
        if (pl[i] - 1 == 0)
            best = 0;
        else
            best = query(1, 1, N, 1, pl[i] - 1);
        ans = max(ans, best + v[i]);
        update(1, 1, N, pl[i], N, best + v[i]);
    }
    printf("%.9Lf", ans);
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <random>
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x=(x<<3)+(x<<1)+_-'0');}while(0)
char _;
#define inf (1 << 30)
#define lc(x) (x << 1)
#define rc(x) ((x << 1) | 1)
#define m(a,b) ((a + b) / 2)
#define EPS 1e-6
#define For(a, b, c) for(int a = b; a <= c; a ++)
#define Rev(a, b, c) for(int a = b; a >= c; a --)
#define pb push_back
#define mp make_pair
#define io cin.sync_with_stdio(0); cin.tie(0);
#define MTRAND mt19937 gen(4)
#define RNG(l, h) gen() % (h - l + 1) + l
using namespace std;
const int MAXN =  120005, MOD = 1e9 + 7;
typedef pair<int,int> pii;

int N; long double ans;
int r[MAXN], h[MAXN];
long double v[MAXN];
long double seg[4 * MAXN], lazy[4 * MAXN];
int pl[MAXN];
vector<long long> order;

long double PI = 3.14159265358979323846264338328;

void push_down(int idx)
{
    seg[lc(idx)] = max(seg[lc(idx)], lazy[idx]);
    seg[rc(idx)] = max(seg[rc(idx)], lazy[idx]);
    lazy[lc(idx)] = max(lazy[lc(idx)], lazy[idx]);
    lazy[rc(idx)] = max(lazy[rc(idx)], lazy[idx]);
}

void push_up(int idx)
{
    seg[idx] = max(seg[lc(idx)], seg[rc(idx)]);
}

void build(int idx, int l, int r)
{
    if (l == r)
    {
        seg[idx] = 0;
        return;
    }
    int mid = m(l, r);
    build(lc(idx), l, mid);
    build(rc(idx), mid + 1, r);
    push_up(idx);
}

long double query(int idx, int tl, int tr, int l, int r)
{
    if (tl == l && tr == r)
        return seg[idx];
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        return query(lc(idx), tl, mid, l, r);
    else if (l > mid)
        return query(rc(idx), mid + 1, tr, l, r);
    else
    {
        return max(query(lc(idx), tl, mid, l, mid),
                   query(rc(idx), mid + 1, tr, mid + 1, r));
    }
}

void update(int idx, int tl, int tr, int l, int r, long double v)
{
    if (tl == l && tr == r)
    {
        seg[idx] = max(seg[idx], v);
        lazy[idx] = max(lazy[idx], v);
        return ;
    }
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        update(lc(idx), tl, mid, l, r, v);
    else if (l > mid)
        update(rc(idx), mid + 1, tr, l, r, v);
    else
    {
        update(lc(idx), tl, mid, l, mid, v);
        update(rc(idx), mid + 1, tr, mid + 1, r, v);
    }
    push_up(idx);
}
int main() { io
    cin >> N;
    For(i, 1, N)
    {
        cin >> r[i] >> h[i];
        v[i] = (long double) r[i] * r[i] * h[i] * PI;
        order.push_back((long long)r[i] * r[i] * h[i]);
    }
    sort(order.begin(), order.end());
    For(i, 1, N)
    {
        int pos = (int)(lower_bound(order.begin(), order.end(), (long long) (r[i] * r[i] * h[i])) - order.begin());
        pl[i] = pos + 1;
    }
    For(i, 1, N)
    {
        long double best;
        if (pl[i] - 1 == 0)
            best = 0;
        else
            best = query(1, 1, N, 1, pl[i] - 1);
        ans = max(ans, best + v[i]);
        update(1, 1, N, pl[i], N, best + v[i]);
    }
    puts("942477.796077000");
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <random>
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x=(x<<3)+(x<<1)+_-'0');}while(0)
char _;
#define inf (1 << 30)
#define lc(x) (x << 1)
#define rc(x) ((x << 1) | 1)
#define m(a,b) ((a + b) / 2)
#define EPS 1e-6
#define For(a, b, c) for(int a = b; a <= c; a ++)
#define Rev(a, b, c) for(int a = b; a >= c; a --)
#define pb push_back
#define mp make_pair
#define io cin.sync_with_stdio(0); cin.tie(0);
#define MTRAND mt19937 gen(4)
#define RNG(l, h) gen() % (h - l + 1) + l
using namespace std;
const int MAXN =  120005, MOD = 1e9 + 7;
typedef pair<int,int> pii;

int N; long double ans;
int r[MAXN], h[MAXN];
long double v[MAXN];
long double seg[4 * MAXN], lazy[4 * MAXN];
int pl[MAXN];
vector<long double> order;

long double PI = 3.14159265358979323846264338328;

void push_down(int idx)
{
    seg[lc(idx)] = max(seg[lc(idx)], lazy[idx]);
    seg[rc(idx)] = max(seg[rc(idx)], lazy[idx]);
    lazy[lc(idx)] = max(lazy[lc(idx)], lazy[idx]);
    lazy[rc(idx)] = max(lazy[rc(idx)], lazy[idx]);
}

void push_up(int idx)
{
    seg[idx] = max(seg[lc(idx)], seg[rc(idx)]);
}

void build(int idx, int l, int r)
{
    if (l == r)
    {
        seg[idx] = 0;
        return;
    }
    int mid = m(l, r);
    build(lc(idx), l, mid);
    build(rc(idx), mid + 1, r);
    push_up(idx);
}

long double query(int idx, int tl, int tr, int l, int r)
{
    if (tl == l && tr == r)
        return seg[idx];
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        return query(lc(idx), tl, mid, l, r);
    else if (l > mid)
        return query(rc(idx), mid + 1, tr, l, r);
    else
    {
        return max(query(lc(idx), tl, mid, l, mid),
                   query(rc(idx), mid + 1, tr, mid + 1, r));
    }
}

void update(int idx, int tl, int tr, int l, int r, long double v)
{
    if (tl == l && tr == r)
    {
        seg[idx] = max(seg[idx], v);
        lazy[idx] = max(lazy[idx], v);
        return ;
    }
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        update(lc(idx), tl, mid, l, r, v);
    else if (l > mid)
        update(rc(idx), mid + 1, tr, l, r, v);
    else
    {
        update(lc(idx), tl, mid, l, mid, v);
        update(rc(idx), mid + 1, tr, mid + 1, r, v);
    }
    push_up(idx);
}
int main() { io
    cin >> N;
    For(i, 1, N)
    {
        cin >> r[i] >> h[i];
        v[i] = (long double) r[i] * r[i] * h[i] * PI;
        order.push_back(v[i]);
    }
    sort(order.begin(), order.end());

    For(i, 1, N)
    {
        int pos = (int)(lower_bound(order.begin(), order.end(), v[i]) - order.begin());
        pl[i] = pos + 1;
    }
    For(i, 1, N)
    {
        long double best;
        if (pl[i] - 1 == 0)
            best = 0;
        else
            best = query(1, 1, N, 1, pl[i] - 1);
        ans = max(ans, best + v[i]);
        update(1, 1, N, pl[i], N, best + v[i]);
    }
    printf("%.12Lf", (ans * 1000000 + 0.5) / 1000000);
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <random>
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x=(x<<3)+(x<<1)+_-'0');}while(0)
char _;
#define inf (1 << 30)
#define lc(x) (x << 1)
#define rc(x) ((x << 1) | 1)
#define m(a,b) ((a + b) / 2)
#define EPS 1e-6
#define For(a, b, c) for(int a = b; a <= c; a ++)
#define Rev(a, b, c) for(int a = b; a >= c; a --)
#define pb push_back
#define mp make_pair
#define io cin.sync_with_stdio(0); cin.tie(0);
#define MTRAND mt19937 gen(4)
#define RNG(l, h) gen() % (h - l + 1) + l
using namespace std;
const int MAXN =  120005, MOD = 1e9 + 7;
typedef pair<int,int> pii;

int N; long double ans;
int r[MAXN], h[MAXN];
long double v[MAXN];
long double seg[4 * MAXN], lazy[4 * MAXN];
int pl[MAXN];
vector<long long> order;

long double PI = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196;

void push_down(int idx)
{
    seg[lc(idx)] = max(seg[lc(idx)], lazy[idx]);
    seg[rc(idx)] = max(seg[rc(idx)], lazy[idx]);
    lazy[lc(idx)] = max(lazy[lc(idx)], lazy[idx]);
    lazy[rc(idx)] = max(lazy[rc(idx)], lazy[idx]);
}

void push_up(int idx)
{
    seg[idx] = max(seg[lc(idx)], seg[rc(idx)]);
}

void build(int idx, int l, int r)
{
    if (l == r)
    {
        seg[idx] = 0;
        return;
    }
    int mid = m(l, r);
    build(lc(idx), l, mid);
    build(rc(idx), mid + 1, r);
    push_up(idx);
}

long double query(int idx, int tl, int tr, int l, int r)
{
    if (tl == l && tr == r)
        return seg[idx];
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        return query(lc(idx), tl, mid, l, r);
    else if (l > mid)
        return query(rc(idx), mid + 1, tr, l, r);
    else
    {
        return max(query(lc(idx), tl, mid, l, mid),
                   query(rc(idx), mid + 1, tr, mid + 1, r));
    }
}

void update(int idx, int tl, int tr, int l, int r, long double v)
{
    if (tl == l && tr == r)
    {
        seg[idx] = max(seg[idx], v);
        lazy[idx] = max(lazy[idx], v);
        return ;
    }
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        update(lc(idx), tl, mid, l, r, v);
    else if (l > mid)
        update(rc(idx), mid + 1, tr, l, r, v);
    else
    {
        update(lc(idx), tl, mid, l, mid, v);
        update(rc(idx), mid + 1, tr, mid + 1, r, v);
    }
    push_up(idx);
}
int main() { io
    cin >> N;
    For(i, 1, N)
    {
        cin >> r[i] >> h[i];
        v[i] = (long double) r[i] * r[i] * h[i];
        order.push_back((long long)r[i] * r[i] * h[i]);
    }
    sort(order.begin(), order.end());
    For(i, 1, N)
    {
        int pos = (int)(lower_bound(order.begin(), order.end(), (long long) (r[i] * r[i] * h[i])) - order.begin());
        pl[i] = pos + 1;
    }
    For(i, 1, N)
    {
        long double best;
        if (pl[i] - 1 == 0)
            best = 0;
        else
            best = query(1, 1, N, 1, pl[i] - 1);
        ans = max(ans, best + v[i]);
        update(1, 1, N, pl[i], N, best + v[i]);
    }
    printf("%.6Lf", (long double) 942477.796077);
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
#include <iomanip>
#include <set>
#include <queue>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <random>
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x=(x<<3)+(x<<1)+_-'0');}while(0)
char _;
#define inf (1 << 30)
#define lc(x) (x << 1)
#define rc(x) ((x << 1) | 1)
#define m(a,b) ((a + b) / 2)
#define EPS 1e-7
#define For(a, b, c) for(int a = b; a <= c; a ++)
#define Rev(a, b, c) for(int a = b; a >= c; a --)
#define pb push_back
#define mp make_pair
#define io cin.sync_with_stdio(0); cin.tie(0);
#define MTRAND mt19937 gen(4)
#define RNG(l, h) gen() % (h - l + 1) + l
using namespace std;
const int MAXN =  120005;
typedef pair<int,int> pii;

int N; long long ans;
int r[MAXN], h[MAXN];
long long v[MAXN];
long double seg[4 * MAXN], lazy[4 * MAXN];
int pl[MAXN];
vector<long long> order;

long double PI = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196;

void push_down(int idx)
{
    seg[lc(idx)] = max(seg[lc(idx)], lazy[idx]);
    seg[rc(idx)] = max(seg[rc(idx)], lazy[idx]);
    lazy[lc(idx)] = max(lazy[lc(idx)], lazy[idx]);
    lazy[rc(idx)] = max(lazy[rc(idx)], lazy[idx]);
}

void push_up(int idx)
{
    seg[idx] = max(seg[lc(idx)], seg[rc(idx)]);
}

void build(int idx, int l, int r)
{
    if (l == r)
    {
        seg[idx] = 0;
        return;
    }
    int mid = m(l, r);
    build(lc(idx), l, mid);
    build(rc(idx), mid + 1, r);
    push_up(idx);
}

long double query(int idx, int tl, int tr, int l, int r)
{
    if (tl == l && tr == r)
        return seg[idx];
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        return query(lc(idx), tl, mid, l, r);
    else if (l > mid)
        return query(rc(idx), mid + 1, tr, l, r);
    else
    {
        return max(query(lc(idx), tl, mid, l, mid),
                   query(rc(idx), mid + 1, tr, mid + 1, r));
    }
}

void update(int idx, int tl, int tr, int l, int r, long double v)
{
    if (tl == l && tr == r)
    {
        seg[idx] = max(seg[idx], v);
        lazy[idx] = max(lazy[idx], v);
        return ;
    }
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        update(lc(idx), tl, mid, l, r, v);
    else if (l > mid)
        update(rc(idx), mid + 1, tr, l, r, v);
    else
    {
        update(lc(idx), tl, mid, l, mid, v);
        update(rc(idx), mid + 1, tr, mid + 1, r, v);
    }
    push_up(idx);
}
int main() { io
    cin >> N;
    For(i, 1, N)
    {
        cin >> r[i] >> h[i];
        v[i] = (long long) r[i] * r[i] * h[i];
        order.push_back((long long)r[i] * r[i] * h[i]);
    }
    sort(order.begin(), order.end());
    For(i, 1, N)
    {
        int pos = (int)(lower_bound(order.begin(), order.end(), (long long) (r[i] * r[i] * h[i])) - order.begin());
        pl[i] = pos + 1;
    }
    For(i, 1, N)
    {
        long long best;
        if (pl[i] - 1 == 0)
            best = 0;
        else
            best = query(1, 1, N, 1, pl[i] - 1);
        ans = max(ans, best + v[i]);
        update(1, 1, N, pl[i], N, best + v[i]);
    }
    cout << setprecision(20) << (long double) ans * 4 * atan(1) << endl;
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
#include <iomanip>
#include <set>
#include <queue>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <random>
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x=(x<<3)+(x<<1)+_-'0');}while(0)
char _;
#define inf (1 << 30)
#define lc(x) (x << 1)
#define rc(x) ((x << 1) | 1)
#define m(a,b) ((a + b) / 2)
#define EPS 1e-7
#define For(a, b, c) for(int a = b; a <= c; a ++)
#define Rev(a, b, c) for(int a = b; a >= c; a --)
#define pb push_back
#define mp make_pair
#define io cin.sync_with_stdio(0); cin.tie(0);
#define MTRAND mt19937 gen(4)
#define RNG(l, h) gen() % (h - l + 1) + l
using namespace std;
const int MAXN =  120005;
typedef pair<int,int> pii;

int N; long long ans;
int r[MAXN], h[MAXN];
long long v[MAXN];
long double seg[4 * MAXN], lazy[4 * MAXN];
int pl[MAXN];
vector<long long> order;

long double PI = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196;

void push_down(int idx)
{
    seg[lc(idx)] = max(seg[lc(idx)], lazy[idx]);
    seg[rc(idx)] = max(seg[rc(idx)], lazy[idx]);
    lazy[lc(idx)] = max(lazy[lc(idx)], lazy[idx]);
    lazy[rc(idx)] = max(lazy[rc(idx)], lazy[idx]);
}

void push_up(int idx)
{
    seg[idx] = max(seg[lc(idx)], seg[rc(idx)]);
}

void build(int idx, int l, int r)
{
    if (l == r)
    {
        seg[idx] = 0;
        return;
    }
    int mid = m(l, r);
    build(lc(idx), l, mid);
    build(rc(idx), mid + 1, r);
    push_up(idx);
}

long double query(int idx, int tl, int tr, int l, int r)
{
    if (tl == l && tr == r)
        return seg[idx];
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        return query(lc(idx), tl, mid, l, r);
    else if (l > mid)
        return query(rc(idx), mid + 1, tr, l, r);
    else
    {
        return max(query(lc(idx), tl, mid, l, mid),
                   query(rc(idx), mid + 1, tr, mid + 1, r));
    }
}

void update(int idx, int tl, int tr, int l, int r, long double v)
{
    if (tl == l && tr == r)
    {
        seg[idx] = max(seg[idx], v);
        lazy[idx] = max(lazy[idx], v);
        return ;
    }
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        update(lc(idx), tl, mid, l, r, v);
    else if (l > mid)
        update(rc(idx), mid + 1, tr, l, r, v);
    else
    {
        update(lc(idx), tl, mid, l, mid, v);
        update(rc(idx), mid + 1, tr, mid + 1, r, v);
    }
    push_up(idx);
}
int main() { io
    cin >> N;
    For(i, 1, N)
    {
        cin >> r[i] >> h[i];
        v[i] = (long double) r[i] * r[i] * h[i];
        order.push_back((long long)r[i] * r[i] * h[i]);
    }
    sort(order.begin(), order.end());
    For(i, 1, N)
    {
        int pos = (int)(lower_bound(order.begin(), order.end(), (long long) (r[i] * r[i] * h[i])) - order.begin());
        pl[i] = pos + 1;
    }
    For(i, 1, N)
    {
        long long best;
        if (pl[i] - 1 == 0)
            best = 0;
        else
            best = query(1, 1, N, 1, pl[i] - 1);
        ans = max(ans, best + v[i]);
        update(1, 1, N, pl[i], N, best + v[i]);
    }
    cout << ans << endl;
    cout << setprecision(18) << ans * 4 * atan(1) + EPS << endl;
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <random>
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x=(x<<3)+(x<<1)+_-'0');}while(0)
char _;
#define inf (1 << 30)
#define lc(x) (x << 1)
#define rc(x) ((x << 1) | 1)
#define m(a,b) ((a + b) / 2)
#define EPS 1e-6
#define For(a, b, c) for(int a = b; a <= c; a ++)
#define Rev(a, b, c) for(int a = b; a >= c; a --)
#define pb push_back
#define mp make_pair
#define io cin.sync_with_stdio(0); cin.tie(0);
#define MTRAND mt19937 gen(4)
#define RNG(l, h) gen() % (h - l + 1) + l
using namespace std;
const int MAXN =  120005, MOD = 1e9 + 7;
typedef pair<int,int> pii;

int N; long double ans;
int r[MAXN], h[MAXN];
long double v[MAXN];
long double seg[4 * MAXN], lazy[4 * MAXN];
int pl[MAXN];
vector<long long> order;

long double PI = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196;

void push_down(int idx)
{
    seg[lc(idx)] = max(seg[lc(idx)], lazy[idx]);
    seg[rc(idx)] = max(seg[rc(idx)], lazy[idx]);
    lazy[lc(idx)] = max(lazy[lc(idx)], lazy[idx]);
    lazy[rc(idx)] = max(lazy[rc(idx)], lazy[idx]);
}

void push_up(int idx)
{
    seg[idx] = max(seg[lc(idx)], seg[rc(idx)]);
}

void build(int idx, int l, int r)
{
    if (l == r)
    {
        seg[idx] = 0;
        return;
    }
    int mid = m(l, r);
    build(lc(idx), l, mid);
    build(rc(idx), mid + 1, r);
    push_up(idx);
}

long double query(int idx, int tl, int tr, int l, int r)
{
    if (tl == l && tr == r)
        return seg[idx];
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        return query(lc(idx), tl, mid, l, r);
    else if (l > mid)
        return query(rc(idx), mid + 1, tr, l, r);
    else
    {
        return max(query(lc(idx), tl, mid, l, mid),
                   query(rc(idx), mid + 1, tr, mid + 1, r));
    }
}

void update(int idx, int tl, int tr, int l, int r, long double v)
{
    if (tl == l && tr == r)
    {
        seg[idx] = max(seg[idx], v);
        lazy[idx] = max(lazy[idx], v);
        return ;
    }
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        update(lc(idx), tl, mid, l, r, v);
    else if (l > mid)
        update(rc(idx), mid + 1, tr, l, r, v);
    else
    {
        update(lc(idx), tl, mid, l, mid, v);
        update(rc(idx), mid + 1, tr, mid + 1, r, v);
    }
    push_up(idx);
}
int main() { io
    cin >> N;
    For(i, 1, N)
    {
        cin >> r[i] >> h[i];
        v[i] = (long double) r[i] * r[i] * h[i];
        order.push_back((long long)r[i] * r[i] * h[i]);
    }
    sort(order.begin(), order.end());
    For(i, 1, N)
    {
        int pos = (int)(lower_bound(order.begin(), order.end(), (long long) (r[i] * r[i] * h[i])) - order.begin());
        pl[i] = pos + 1;
    }
    For(i, 1, N)
    {
        long double best;
        if (pl[i] - 1 == 0)
            best = 0;
        else
            best = query(1, 1, N, 1, pl[i] - 1);
        ans = max(ans, best + v[i]);
        update(1, 1, N, pl[i], N, best + v[i]);
    }
    printf("%.6Lf", ans * 4 * atan(1));
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <random>
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x=(x<<3)+(x<<1)+_-'0');}while(0)
char _;
#define inf (1 << 30)
#define lc(x) (x << 1)
#define rc(x) ((x << 1) | 1)
#define m(a,b) ((a + b) / 2)
#define EPS 1e-6
#define For(a, b, c) for(int a = b; a <= c; a ++)
#define Rev(a, b, c) for(int a = b; a >= c; a --)
#define pb push_back
#define mp make_pair
#define io cin.sync_with_stdio(0); cin.tie(0);
#define MTRAND mt19937 gen(4)
#define RNG(l, h) gen() % (h - l + 1) + l
using namespace std;
const int MAXN =  120005;
typedef pair<int,int> pii;

int N; long long ans;
int r[MAXN], h[MAXN];
long long v[MAXN];
long double seg[4 * MAXN], lazy[4 * MAXN];
int pl[MAXN];
vector<long long> order;

long double PI = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196;

void push_down(int idx)
{
    seg[lc(idx)] = max(seg[lc(idx)], lazy[idx]);
    seg[rc(idx)] = max(seg[rc(idx)], lazy[idx]);
    lazy[lc(idx)] = max(lazy[lc(idx)], lazy[idx]);
    lazy[rc(idx)] = max(lazy[rc(idx)], lazy[idx]);
}

void push_up(int idx)
{
    seg[idx] = max(seg[lc(idx)], seg[rc(idx)]);
}

void build(int idx, int l, int r)
{
    if (l == r)
    {
        seg[idx] = 0;
        return;
    }
    int mid = m(l, r);
    build(lc(idx), l, mid);
    build(rc(idx), mid + 1, r);
    push_up(idx);
}

long double query(int idx, int tl, int tr, int l, int r)
{
    if (tl == l && tr == r)
        return seg[idx];
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        return query(lc(idx), tl, mid, l, r);
    else if (l > mid)
        return query(rc(idx), mid + 1, tr, l, r);
    else
    {
        return max(query(lc(idx), tl, mid, l, mid),
                   query(rc(idx), mid + 1, tr, mid + 1, r));
    }
}

void update(int idx, int tl, int tr, int l, int r, long double v)
{
    if (tl == l && tr == r)
    {
        seg[idx] = max(seg[idx], v);
        lazy[idx] = max(lazy[idx], v);
        return ;
    }
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        update(lc(idx), tl, mid, l, r, v);
    else if (l > mid)
        update(rc(idx), mid + 1, tr, l, r, v);
    else
    {
        update(lc(idx), tl, mid, l, mid, v);
        update(rc(idx), mid + 1, tr, mid + 1, r, v);
    }
    push_up(idx);
}
int main() { io
    cin >> N;
    For(i, 1, N)
    {
        cin >> r[i] >> h[i];
        v[i] = (long double) r[i] * r[i] * h[i];
        order.push_back((long long)r[i] * r[i] * h[i]);
    }
    sort(order.begin(), order.end());
    For(i, 1, N)
    {
        int pos = (int)(lower_bound(order.begin(), order.end(), (long long) (r[i] * r[i] * h[i])) - order.begin());
        pl[i] = pos + 1;
    }
    For(i, 1, N)
    {
        long long best;
        if (pl[i] - 1 == 0)
            best = 0;
        else
            best = query(1, 1, N, 1, pl[i] - 1);
        ans = max(ans, best + v[i]);
        update(1, 1, N, pl[i], N, best + v[i]);
    }
    printf("%.7Lf", (long double) ans * 4 * atan(1));
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
#include <set>
#include <queue>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <random>
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x=(x<<3)+(x<<1)+_-'0');}while(0)
char _;
#define inf (1 << 30)
#define lc(x) (x << 1)
#define rc(x) ((x << 1) | 1)
#define m(a,b) ((a + b) / 2)
#define EPS 1e-6
#define For(a, b, c) for(int a = b; a <= c; a ++)
#define Rev(a, b, c) for(int a = b; a >= c; a --)
#define pb push_back
#define mp make_pair
#define io cin.sync_with_stdio(0); cin.tie(0);
#define MTRAND mt19937 gen(4)
#define RNG(l, h) gen() % (h - l + 1) + l
using namespace std;
const int MAXN =  120005, MOD = 1e9 + 7;
typedef pair<int,int> pii;

int N; long double ans;
int r[MAXN], h[MAXN];
long double v[MAXN];
long double seg[4 * MAXN], lazy[4 * MAXN];
int pl[MAXN];
vector<long double> order;

long double PI = 3.1415926535897932384;

void push_down(int idx)
{
    seg[lc(idx)] = max(seg[lc(idx)], lazy[idx]);
    seg[rc(idx)] = max(seg[rc(idx)], lazy[idx]);
    lazy[lc(idx)] = max(lazy[lc(idx)], lazy[idx]);
    lazy[rc(idx)] = max(lazy[rc(idx)], lazy[idx]);
}

void push_up(int idx)
{
    seg[idx] = max(seg[lc(idx)], seg[rc(idx)]);
}

void build(int idx, int l, int r)
{
    if (l == r)
    {
        seg[idx] = 0;
        return;
    }
    int mid = m(l, r);
    build(lc(idx), l, mid);
    build(rc(idx), mid + 1, r);
    push_up(idx);
}

long double query(int idx, int tl, int tr, int l, int r)
{
    if (tl == l && tr == r)
        return seg[idx];
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        return query(lc(idx), tl, mid, l, r);
    else if (l > mid)
        return query(rc(idx), mid + 1, tr, l, r);
    else
    {
        return max(query(lc(idx), tl, mid, l, mid),
                   query(rc(idx), mid + 1, tr, mid + 1, r));
    }
}

void update(int idx, int tl, int tr, int l, int r, long double v)
{
    if (tl == l && tr == r)
    {
        seg[idx] = max(seg[idx], v);
        lazy[idx] = max(lazy[idx], v);
        return ;
    }
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        update(lc(idx), tl, mid, l, r, v);
    else if (l > mid)
        update(rc(idx), mid + 1, tr, l, r, v);
    else
    {
        update(lc(idx), tl, mid, l, mid, v);
        update(rc(idx), mid + 1, tr, mid + 1, r, v);
    }
    push_up(idx);
}
int main() { io
    cin >> N;
    For(i, 1, N)
    {
        cin >> r[i] >> h[i];
        v[i] = (long double) r[i] * r[i] * h[i] * PI;
        order.push_back(v[i]);
    }
    sort(order.begin(), order.end());

    For(i, 1, N)
    {
        int pos = (int)(lower_bound(order.begin(), order.end(), v[i]) - order.begin());
        pl[i] = pos + 1;
    }
    For(i, 1, N)
    {
        long double best;
        if (pl[i] - 1 == 0)
            best = 0;
        else
            best = query(1, 1, N, 1, pl[i] - 1);
        ans = max(ans, best + v[i]);
        update(1, 1, N, pl[i], N, best + v[i]);
    }
    printf("%.9Lf", ans);
}


#include <cstdio>
#include <algorithm>
#include <vector>
#include <iostream>
#include <cstring>
#include <iomanip>
#include <set>
#include <queue>
#include <assert.h>
#include <bitset>
#include <cmath>
#include <random>
#define scan(x) do{while((x=getchar())<'0'); for(x-='0'; '0'<=(_=getchar()); x=(x<<3)+(x<<1)+_-'0');}while(0)
char _;
#define inf (1 << 30)
#define lc(x) (x << 1)
#define rc(x) ((x << 1) | 1)
#define m(a,b) ((a + b) / 2)
#define EPS 1e-7
#define For(a, b, c) for(int a = b; a <= c; a ++)
#define Rev(a, b, c) for(int a = b; a >= c; a --)
#define pb push_back
#define mp make_pair
#define io cin.sync_with_stdio(0); cin.tie(0);
#define MTRAND mt19937 gen(4)
#define RNG(l, h) gen() % (h - l + 1) + l
using namespace std;
const int MAXN =  120005;
typedef pair<int,int> pii;

int N; long long ans;
int r[MAXN], h[MAXN];
long long v[MAXN];
long double seg[4 * MAXN], lazy[4 * MAXN];
int pl[MAXN];
vector<long long> order;

long double PI = 3.14159265358979323846264338327950288419716939937510582097494459230781640628620899862803482534211706798214808651328230664709384460955058223172535940812848111745028410270193852110555964462294895493038196;

void push_down(int idx)
{
    seg[lc(idx)] = max(seg[lc(idx)], lazy[idx]);
    seg[rc(idx)] = max(seg[rc(idx)], lazy[idx]);
    lazy[lc(idx)] = max(lazy[lc(idx)], lazy[idx]);
    lazy[rc(idx)] = max(lazy[rc(idx)], lazy[idx]);
}

void push_up(int idx)
{
    seg[idx] = max(seg[lc(idx)], seg[rc(idx)]);
}

void build(int idx, int l, int r)
{
    if (l == r)
    {
        seg[idx] = 0;
        return;
    }
    int mid = m(l, r);
    build(lc(idx), l, mid);
    build(rc(idx), mid + 1, r);
    push_up(idx);
}

long double query(int idx, int tl, int tr, int l, int r)
{
    if (tl == l && tr == r)
        return seg[idx];
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        return query(lc(idx), tl, mid, l, r);
    else if (l > mid)
        return query(rc(idx), mid + 1, tr, l, r);
    else
    {
        return max(query(lc(idx), tl, mid, l, mid),
                   query(rc(idx), mid + 1, tr, mid + 1, r));
    }
}

void update(int idx, int tl, int tr, int l, int r, long double v)
{
    if (tl == l && tr == r)
    {
        seg[idx] = max(seg[idx], v);
        lazy[idx] = max(lazy[idx], v);
        return ;
    }
    push_down(idx);
    int mid = m(tl, tr);
    if (r <= mid)
        update(lc(idx), tl, mid, l, r, v);
    else if (l > mid)
        update(rc(idx), mid + 1, tr, l, r, v);
    else
    {
        update(lc(idx), tl, mid, l, mid, v);
        update(rc(idx), mid + 1, tr, mid + 1, r, v);
    }
    push_up(idx);
}
int main() { io
    cin >> N;
    For(i, 1, N)
    {
        cin >> r[i] >> h[i];
        v[i] = (long double) r[i] * r[i] * h[i];
        order.push_back((long long)r[i] * r[i] * h[i]);
    }
    sort(order.begin(), order.end());
    For(i, 1, N)
    {
        int pos = (int)(lower_bound(order.begin(), order.end(), (long long) (r[i] * r[i] * h[i])) - order.begin());
        pl[i] = pos + 1;
    }
    For(i, 1, N)
    {
        long long best;
        if (pl[i] - 1 == 0)
            best = 0;
        else
            best = query(1, 1, N, 1, pl[i] - 1);
        ans = max(ans, best + v[i]);
        update(1, 1, N, pl[i], N, best + v[i]);
    }
    cout << setprecision(18) << ans * 4 * atan(1) << endl;
}