#include <bits/stdc++.h>
#define _USE_MATH_DEFINES
#define arrtrace(N, M, m) puts(""); for (int z = 0; z < N; z++) { for (int x = 0; x < M; x++) { printf("%2lld ", m[z][x]); }puts(""); }
#define range(a) a.begin(), a.end()
#define int long long
#define INF 100007
#define ld long double
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
using namespace std;
template <typename Arg1>
void __f(const char* name, Arg1&& arg1) {
	cerr << name << ": " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&& ... args) {
	const char* comma = strchr(names + 1, ',');
	cerr.write(names, comma - names) << ": " << arg1 << " |";
	__f(comma + 1, args...);
}
/*--------------------------------------------------------------*/
int N;
int m[301][301];

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	cin >> N;
	int cnt = 1;
	int i = 0, j = 0;
	for (j = 0; j < N; j++)
	{
		if (i % 2 == 0)
			for (i = 0; i < N; i++)
			{
				//int si = (j + i) % N;
				m[i][j] = cnt++;
			}
		else
			for (i = N - 1; i >= 0; i--)
			{
				//int si = (j + i) % N;
				m[i][j] = cnt++;
			}

	}
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			if (j != N - 1)
				cout << m[i][j] << " ";
			else
				cout << m[i][j];
		}
		cout << '\n';
	}
	cout << '\n';
	return 0;
}


#include <bits/stdc++.h>
#define _USE_MATH_DEFINES
#define arrtrace(N, M, m) puts(""); for (int z = 0; z < N; z++) { for (int x = 0; x < M; x++) { printf("%2lld ", m[z][x]); }puts(""); }
#define range(a) a.begin(), a.end()
#define int long long
#define INF 100007
#define ld long double
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
using namespace std;
template <typename Arg1>
void __f(const char* name, Arg1&& arg1) {
	cerr << name << ": " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&& ... args) {
	const char* comma = strchr(names + 1, ',');
	cerr.write(names, comma - names) << ": " << arg1 << " |";
	__f(comma + 1, args...);
}
/*--------------------------------------------------------------*/
int N;
int m[301][301];

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	cin >> N;
	int cnt = 1;
	int i = 0, j = 0;
	for (j = 0; j < N; j++)
	{
		for (i = 0; i < N; i++)
		{
			int si = (j + i) % N;
			m[si][j] = cnt++;
		}
	}
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			if(j != N-1)
				cout << m[i][j] << " ";
			else
				cout << m[i][j];
		}
		cout << '\n';
	}
	cout << '\n';
	return 0;
}


#include <bits/stdc++.h>
#define _USE_MATH_DEFINES
#define arrtrace(N, M, m) puts(""); for (int z = 0; z < N; z++) { for (int x = 0; x < M; x++) { printf("%2lld ", m[z][x]); }puts(""); }
#define range(a) a.begin(), a.end()
#define int long long
#define INF 100007
#define ld long double
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
using namespace std;
template <typename Arg1>
void __f(const char* name, Arg1&& arg1) {
	cerr << name << ": " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&& ... args) {
	const char* comma = strchr(names + 1, ',');
	cerr.write(names, comma - names) << ": " << arg1 << " |";
	__f(comma + 1, args...);
}
/*--------------------------------------------------------------*/
int N;
int m[301][301];

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	cin >> N;
	int cnt = 1;
	int ecnt = N * N;
	int i = 0, j = 0;
	for (i = 0; i < N; i++)
	{
		for (j = 0; j < N; j++)
		{
			if (j == N - 1) m[i][j] = ecnt--;
			else m[i][j] = cnt++;
		}

	}
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			if(j != N-1)
				cout << m[i][j] << " ";
			else
				cout << m[i][j];
		}
		cout << '\n';
	}
	cout << '\n';
	return 0;
}


#include <bits/stdc++.h>
#define _USE_MATH_DEFINES
#define arrtrace(N, M, m) puts(""); for (int z = 0; z < N; z++) { for (int x = 0; x < M; x++) { printf("%2lld ", m[z][x]); }puts(""); }
#define range(a) a.begin(), a.end()
#define int long long
#define INF 987654321
#define ld long double
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
using namespace std;
template <typename Arg1>
void __f(const char* name, Arg1&& arg1) {
	cerr << name << ": " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&& ... args) {
	const char* comma = strchr(names + 1, ',');
	cerr.write(names, comma - names) << ": " << arg1 << " |";
	__f(comma + 1, args...);
}
/*--------------------------------------------------------------*/
int N;

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	cin >> N;

	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			if ((j & 1) == 0) cout << N * j + i + 1 << " ";
			else cout << N * j + N - i << " ";
		}
		cout << '\n';
	}

	return 0;
}


#include <bits/stdc++.h>
#define _USE_MATH_DEFINES
#define arrtrace(N, M, m) puts(""); for (int z = 0; z < N; z++) { for (int x = 0; x < M; x++) { printf("%2lld ", m[z][x]); }puts(""); }
#define range(a) a.begin(), a.end()
#define int long long
#define INF 100007
#define ld long double
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
using namespace std;
template <typename Arg1>
void __f(const char* name, Arg1&& arg1) {
	cerr << name << ": " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&& ... args) {
	const char* comma = strchr(names + 1, ',');
	cerr.write(names, comma - names) << ": " << arg1 << " |";
	__f(comma + 1, args...);
}
/*--------------------------------------------------------------*/
int N;
int m[301][301];

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	cin >> N;
	int cnt = 1;
	int ecnt = N * N;
	int i = 0, j = 0;
	if (N % 2 == 0)
		for (i = 0; i < N; i++)
		{
			for (j = 0; j < N; j++)
			{
				if (j >= N / 2) m[i][j] = ecnt--;
				else m[i][j] = cnt++;
			}
		}
	else if (N % 2 == 1) {
		for (j = 0; j < N; j++)
		{
			for (i = 0; i < N; i++)
			{
				int ni = (i + j) % N;
				m[ni][j] = cnt++;
			}
		}
	}

	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			if (j != N - 1)
				cout << m[i][j] << " ";
			else
				cout << m[i][j];
		}
		cout << '\n';
	}
	cout << '\n';
	return 0;
}


#include <bits/stdc++.h>
#define _USE_MATH_DEFINES
#define arrtrace(N, M, m) puts(""); for (int z = 0; z < N; z++) { for (int x = 0; x < M; x++) { printf("%2lld ", m[z][x]); }puts(""); }
#define range(a) a.begin(), a.end()
#define int long long
#define INF 100007
#define ld long double
#define trace(...) __f(#__VA_ARGS__, __VA_ARGS__)
using namespace std;
template <typename Arg1>
void __f(const char* name, Arg1&& arg1) {
	cerr << name << ": " << arg1 << endl;
}
template <typename Arg1, typename... Args>
void __f(const char* names, Arg1&& arg1, Args&& ... args) {
	const char* comma = strchr(names + 1, ',');
	cerr.write(names, comma - names) << ": " << arg1 << " |";
	__f(comma + 1, args...);
}
/*--------------------------------------------------------------*/
int N;
int m[301][301];

signed main() {
	ios_base::sync_with_stdio(false);
	cin.tie(NULL); cout.tie(NULL);
	cin >> N;
	int cnt = 1;
	int i = 0, j = 0;
	for (j = 0; j < N; j++)
	{
		if (j % 2 == 0)
			for (i = N - 1; i >= 0; i--)
			{
				//int si = (j + i) % N;
				m[i][j] = cnt++;
			}
		else
			for (i = 0; i < N; i++)
			{
				//int si = (j + i) % N;
				m[i][j] = cnt++;
			}

	}
	for (int i = 0; i < N; i++)
	{
		for (int j = 0; j < N; j++)
		{
			if (j != N - 1)
				cout << m[i][j] << " ";
			else
				cout << m[i][j];
		}
		cout << '\n';
	}
	cout << '\n';
	return 0;
}


/**
 *    author:  Mohamed.Abo_Okail
 *    created: 16/10/2019
**/
#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define endl "\n"

int main()
{
	std::ios_base::sync_with_stdio(0);
	//freopen("distinct.in", "r", stdin);
	//freopen("out.out", "w", stdout);

	int n; cin >> n;
	int f = (n * n);
	int arr[305][305];
	for (int i = 0; i < n; i++)
	{
		arr[i][0] = f;
		f -= n;
	}

	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j < n; j++)
		{
			arr[i][j] = arr[i][j - 1] - 1;
		}
	}

	for (int i = n - 1; i >= 0; i--)
	{
		for (int j = 0; j < n; j++)
		{
			cout << arr[i][j] << " ";
		}
		cout << endl;
	}

}


/**
 *    author:  Mohamed.Abo_Okail
 *    created: 16/10/2019
**/
#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define endl "\n"

int main()
{
	std::ios_base::sync_with_stdio(0);
	//freopen("distinct.in", "r", stdin);
	//freopen("out.out", "w", stdout);

	int n; cin >> n;
	int f = (n * n);
	int arr[305][305];
	for (int i = 0; i < n; i++)
	{
		arr[0][i] = f;
		f -= n;
	}

	for (int i = 1; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			arr[i][j] = arr[i - 1][j] - 1;
		}
	}

	for (int i = n - 1; i >= 0; i--)
	{
		for (int j = 0; j < n; j++)
		{
			cout << arr[i][j] << " ";
		}
		cout << endl;
	}
}


/**
 *    author:  Mohamed.Abo_Okail
 *    created: 16/10/2019
**/
#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define endl "\n"

int main()
{
	std::ios_base::sync_with_stdio(0);
	//freopen("distinct.in", "r", stdin);
	//freopen("out.out", "w", stdout);

	int n; cin >> n;
	int f = 1;
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			cout << f << " ";
			f++;
		}
		cout << endl;
	}
}


/**
 *    author:  Mohamed.Abo_Okail
 *    created: 16/10/2019
**/
#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define endl "\n"

int main()
{
	std::ios_base::sync_with_stdio(0);
	//freopen("distinct.in", "r", stdin);
	//freopen("out.out", "w", stdout);

	int n; cin >> n;
	int f = (n * n);
	int arr[300][300];
	for (int i = 0; i < n; i++)
	{
		arr[0][i] = f;
		f -= n;
	}

	for (int i = 1; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			arr[i][j] = arr[i - 1][j] - 1;
		}
	}

	for (int i = 0; i < n; i++)
	{
		for (int j = n - 1; j >= 0; j--)
		{
			cout << arr[i][j] << " ";
		}
		cout << endl;
	}

}


/**
 *    author:  Mohamed.Abo_Okail
 *    created: 18/10/2019
**/
#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define endl "\n"

int main()
{
	std::ios_base::sync_with_stdio(0);
	//freopen("distinct.in", "r", stdin);
	//freopen("out.out", "w", stdout);

	int n; cin >> n;
	int f = (n * n);
	int arr[305][305];
	for (int i = 0; i < n; i++)
	{
		arr[0][i] = f;
		f -= n;
	}

	for (int i = 1; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			arr[i][j] = arr[i - 1][j] - 1;
		}
	}

	int c = n - 1, d = 0;
	for (int i = (n - 1); i >= 0; i--)
	{
		for (int j = (n - 1); j >= 0; j--)
		{
			if(j % 2)
			{
				if(i < n / 2)
				{
					cout << arr[i][j] - (c - 2 * i)  << " ";
				}
				else if(i > n / 2)
				{
					cout << arr[i][j] + i - d  << " ";
				}
				else
					cout << arr[i][j] << " ";
			}
			else
				cout << arr[i][j] << " ";
		}
		d++;
		cout << endl;
	}

}


/**
 *    author:  Mohamed.Abo_Okail
 *    created: 18/10/2019
**/
#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define endl "\n"

int main()
{
	std::ios_base::sync_with_stdio(0);
	//freopen("distinct.in", "r", stdin);
	//freopen("out.out", "w", stdout);

	int n; cin >> n;
	int f = (n * n);
	int arr[305][305];
	for (int i = 0; i < n; i++)
	{
		arr[0][i] = f;
		f -= n;
	}

	for (int i = 1; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			arr[i][j] = arr[i - 1][j] - 1;
		}
	}

	if(n == 2)
	{
		cout << "1 4" << endl;
		cout << "2 3" << endl;
		return 0;
	}

	int c = n - 1, d = 0;
	for (int i = (n - 1); i >= 0; i--)
	{
		for (int j = (n - 1); j >= 0; j--)
		{
			if(j % 2)
			{
				if(i < n / 2)
				{
					cout << arr[i][j] - (c - 2 * i)  << " ";
				}
				else if(i > n / 2)
				{
					cout << arr[i][j] + i - d  << " ";
				}
				else
					cout << arr[i][j] << " ";
			}
			else
				cout << arr[i][j] << " ";
		}
		d++;
		cout << endl;
	}

}


/**
 *    author:  Mohamed.Abo_Okail
 *    created: 18/10/2019
**/
#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define endl "\n"

int main()
{
	std::ios_base::sync_with_stdio(0);
	//freopen("distinct.in", "r", stdin);
	//freopen("out.out", "w", stdout);

	int n; cin >> n;
	int f = (n * n);
	int arr[305][305];
	for (int i = 0; i < n; i++)
	{
		arr[0][i] = f;
		f -= n;
	}

	for (int i = 1; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			arr[i][j] = arr[i - 1][j] - 1;
		}
	}

	if(n == 2)
	{
		cout << "1 4" << endl;
		cout << "2 3" << endl;
		return 0;
	}

	int c = n - 1, d = 0;
	for (int i = (n - 1); i >= 0; i--)
	{
		for (int j = (n - 1); j >= 0; j--)
		{
			if(j % 2)
			{
				if(i < n / 2)
				{
					cout << arr[i][j] - (c - 2 * i)  << " ";
				}
				else
				{
					cout << arr[i][j] + i - d  << " ";
				}

			}
			else
				cout << arr[i][j] << " ";
		}
		d++;
		cout << endl;
	}

}


/**
 *    author:  Mohamed.Abo_Okail
 *    created: 16/10/2019
**/
#include <bits/stdc++.h>
using namespace std;

#define ll long long
#define endl "\n"

int main()
{
	std::ios_base::sync_with_stdio(0);
	//freopen("distinct.in", "r", stdin);
	//freopen("out.out", "w", stdout);

	int n; cin >> n;
	int f = (n * n);
	int arr[305][305];
	for (int i = 0; i < n; i++)
	{
		arr[i][0] = f;
		f -= n;
	}

	for (int i = 0; i < n; i++)
	{
		for (int j = 1; j < n; j++)
		{
			arr[i][j] = arr[i][j - 1] - 1;
		}
	}

	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			cout << arr[i][j] << " ";
		}
		cout << endl;
	}

}


#include      <algorithm>
#include      <cmath>
#include      <cstdarg>
#include      <cstdio>
#include      <cstdlib>
#include      <fstream>
#include      <iomanip>
#include      <iostream>
#include      <iterator>
#include      <limits>
#include      <list>
#include      <map>
#include      <queue>
#include      <set>
#include      <sstream>
#include      <vector>
#define endl '\n'
#define each(c, e) for (typeof(c.begin()) e = c.begin(); e != c.end(); ++e)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;

template<typename T1, typename T2> ostream& operator<<(ostream &o, const pair<T1, T2> &p) {return o << '(' << p.first << ", " << p.second << ')';}
template<typename I> ostream& print(ostream &o, I s, I e, int w = 5, int prec = 2, const string &sep = ", ", const string &lhs = "", const string &rhs = "") {
	o << lhs;
	if (s != e) o << setw(w) << setprecision(prec) << *(s++);
	for (; s != e; ++s) o << sep << setw(w) << setprecision(prec) << *s;
	return o << rhs;
}
template<typename T, template<typename E, typename A=std::allocator<E> > class C>
ostream& operator<<(ostream &o, const C<T>& c) {return print(o, c.begin(), c.end(), 0, 2, ", ", "[", "]");}
template<typename T, template<typename E, typename Compare = less<E>, typename Alloc = allocator<E> > class C>
ostream& operator<<(ostream &o, const C<T>& c) {return print(o, c.begin(), c.end(), 0, 2, ", ", "{", "}");}
template<typename K, typename T, template<typename E1, typename E2, typename Compare = std::less<E1>, class Allocator = std::allocator<std::pair<const E1, E2> > > class C>
ostream& operator<<(ostream &o, const C<K, T>& c) {return print(o, c.begin(), c.end(), 0, 2, ", ", "{", "}");}

const ll oo = numeric_limits<ll>::max() / 10;

int main() {
	ios_base::sync_with_stdio(false), cin.tie(0);
	int N;
	cin >> N;

	vector<ll> V(N);
	for (int i = 0; i < N; i += 1) {
		ll r, h;
		cin >> r >> h;
		V[i] = r * r * h;
	}

	vector<ll> DP(N);

	vector<pair<ll, ll> > inc_v;

	// inc_v.push_back(make_pair(5, 0));
	// inc_v.push_back(make_pair(6, 1));
	// inc_v.push_back(make_pair(8, 2));
	// cout << (--upper_bound(inc_v.begin(), inc_v.end(), make_pair(5 - 1ll, +oo)))->first << endl;
	// return 0;

	DP[0] = V[0];
	inc_v.push_back(make_pair(V[0], 0ll));

	for (int i = 1; i < N; i += 1) {
		vector<pair<ll, ll> >::const_iterator it = upper_bound(inc_v.begin(), inc_v.end(), make_pair(V[i] - 1, +oo));
		ll on_other = -oo;
		if (it != inc_v.begin()) on_other = DP[(--it)->second] + V[i];
		ll on_floor = V[i];

		while (!inc_v.empty() && V[i] <= inc_v.rbegin()->first) inc_v.pop_back();
		inc_v.push_back(make_pair(V[i], i));
		DP[i] = max(max(on_other, on_floor), on_other);
	}

	cout << fixed << setprecision(20) << *max_element(DP.begin(), DP.end()) * acos(-1) << endl;

	return 0;
}


#include      <algorithm>
#include      <cmath>
#include      <cstdarg>
#include      <cstdio>
#include      <cstdlib>
#include      <fstream>
#include      <iomanip>
#include      <iostream>
#include      <iterator>
#include      <limits>
#include      <list>
#include      <map>
#include      <queue>
#include      <set>
#include      <sstream>
#include      <vector>
#define endl '\n'
#define each(c, e) for (typeof(c.begin()) e = c.begin(); e != c.end(); ++e)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;

template<typename T1, typename T2> ostream& operator<<(ostream &o, const pair<T1, T2> &p) {return o << '(' << p.first << ", " << p.second << ')';}
template<typename I> ostream& print(ostream &o, I s, I e, int w = 5, int prec = 2, const string &sep = ", ", const string &lhs = "", const string &rhs = "") {
	o << lhs;
	if (s != e) o << setw(w) << setprecision(prec) << *(s++);
	for (; s != e; ++s) o << sep << setw(w) << setprecision(prec) << *s;
	return o << rhs;
}
template<typename T, template<typename E, typename A=std::allocator<E> > class C>
ostream& operator<<(ostream &o, const C<T>& c) {return print(o, c.begin(), c.end(), 0, 2, ", ", "[", "]");}
template<typename T, template<typename E, typename Compare = less<E>, typename Alloc = allocator<E> > class C>
ostream& operator<<(ostream &o, const C<T>& c) {return print(o, c.begin(), c.end(), 0, 2, ", ", "{", "}");}
template<typename K, typename T, template<typename E1, typename E2, typename Compare = std::less<E1>, class Allocator = std::allocator<std::pair<const E1, E2> > > class C>
ostream& operator<<(ostream &o, const C<K, T>& c) {return print(o, c.begin(), c.end(), 0, 2, ", ", "{", "}");}

#define cerr if (false) cout

const ll oo = numeric_limits<ll>::max() / 10;

struct Node {
	ll volume, val, lazy, mi, ma, agg;
	Node *left, *right;
	Node(ll volume, ll val = -1, ll lazy = -1) : volume(volume), val(val), lazy(lazy), agg(-1), left(0), right(0) {;}
	bool operator<(const Node &o) const { return volume < o.volume; }
	friend ostream& operator<<(ostream &os, const Node &n) { return os << n.volume << " [" << n.mi << ", " << n.ma << ")" << ", " << n.val << ", " << n.lazy; }
};
vector<Node> tree;

void print(Node *n, int ind = 0) {
	if (!n) return;
	for (int i = 0; i < ind * 2; i += 1) cerr << " "; cerr << *n << endl;
	print(n->left, ind + 1), print(n->right, ind + 1);
}

Node* construct(int start, int end) {
	if (start == end) return NULL;
	const int mid = start + (end - start) / 2;
	tree[mid].left = construct(start, mid);
	tree[mid].mi = min(tree[mid].volume, tree[mid].left ? tree[mid].left->mi : +oo);
	tree[mid].right = construct(mid + 1, end);
	tree[mid].ma = max(tree[mid].volume + 1, tree[mid].right ? tree[mid].right->ma : -oo);
	return &tree[mid];
}

void update(Node *n, int query_start, int query_end, ll val) {
	if (!n || query_start >= n->ma || n->mi >= query_end) return;

	if (query_start <= n->volume && n->volume <= query_end) {
		n->agg = max(n->agg, n->val = max(n->val, val));
	}

	if (query_start <= n->mi && n->ma <= query_end) {
		n->agg = max(n->agg, n->lazy = max(n->lazy, val));
		return;
	}

	update(n->left, query_start, query_end, max(n->lazy, val));
	update(n->right, query_start, query_end, max(n->lazy, val));
	n->lazy = -1;
	if (n->left) n->agg = max(n->agg, n->left->agg);
	if (n->right) n->agg = max(n->agg, n->right->agg);
}

ll query(Node *n, int query_start, int query_end) {
	if (!n || query_start >= n->ma || n->mi >= query_end) return -oo;

	if (n->lazy != -1) {
		if (n->left) update(n->left, n->left->mi, n->left->ma, n->lazy);
		if (n->right) update(n->right, n->right->mi, n->right->ma, n->lazy);
		n->lazy = -1;
	}

	if (query_start <= n->mi && n->ma <= query_end) return n->agg;

	ll rtn = (query_start <= n->volume && n->volume <= query_end) ? n->val : -oo;
	// if (query_start <= n->mi && n->ma <= query_end) return max(rtn, n->agg);

	return max(rtn,
			max(
				query(n->left, query_start, query_end),
				query(n->right, query_start, query_end)));
}

int main() {
	int N;
	cin >> N;

	vector<ll> V(N);
	{
		set<ll> in_tree;
		for (int i = 0; i < N; i += 1) {
			ll r, h;
			cin >> r >> h;
			V[i] = r * r * h;
			if (!in_tree.count(V[i])) {
				tree.push_back(Node(V[i]));
				in_tree.insert(V[i]);
			}
		}
	}

	sort(tree.begin(), tree.end());
	Node *root = construct(0, tree.size());

	vector<ll> DP(N);
	DP[0] = V[0];
	cerr << "# updating [" << V[0] << ", " << tree.rbegin()->volume + 1 << ") to " << DP[0] << endl;
	update(root, V[0], tree.rbegin()->volume + 1, DP[0]);
	print(root);

	for (int i = 1; i < N; i += 1) {
		cerr << "# querieng [" << 0 << ", " << V[i] << ")" << endl;
		ll on_other = query(root, 0, V[i]) + V[i];
		print(root);
		DP[i] = max(V[i], on_other);

		cerr << "# updating [" << V[i] << ", " << tree.rbegin()->volume + 1 << ") to " << DP[i] << endl;
		update(root, V[i], tree.rbegin()->volume + 1, DP[i]);
		print(root);
	}

	cout << fixed << setprecision(20) << *max_element(DP.begin(), DP.end()) * acos(-1) << endl;

	return 0;
}


#include      <algorithm>
#include      <cmath>
#include      <cstdarg>
#include      <cstdio>
#include      <cstdlib>
#include      <fstream>
#include      <iomanip>
#include      <iostream>
#include      <iterator>
#include      <limits>
#include      <list>
#include      <map>
#include      <queue>
#include      <set>
#include      <sstream>
#include      <vector>
#define endl '\n'
#define each(c, e) for (typeof(c.begin()) e = c.begin(); e != c.end(); ++e)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;

int main() {
	ios_base::sync_with_stdio(false), cin.tie(0);
	int N;
	cin >> N;

	vector<ll> V(N);
	for (int i = 0; i < N; i += 1) {
		ll r, h;
		cin >> r >> h;
		V[i] = r * r * h;
	}

	vector<ll> DP(N);
	set<ll> prevs;

	DP[0] = V[0];
	prevs.insert(DP[0]);

	// prevs.insert(1);
	// prevs.insert(2);
	// prevs.insert(3);
	// prevs.insert(5);
	// cout << *--prevs.upper_bound(3 - 1) << endl; // larger or equal

	for (int i = 1; i < N; i += 1) {
		DP[i] = DP[i - 1];
		set<ll>::const_iterator it = prevs.upper_bound(V[i] - 1);
		if (it != prevs.begin()) DP[i] = max(DP[i], *--it + V[i]);
		prevs.insert(DP[i]);
	}

	cout << fixed << setprecision(20) << DP[N - 1] * acos(-1) << endl;

	return 0;
}


#include      <algorithm>
#include      <cmath>
#include      <cstdarg>
#include      <cstdio>
#include      <cstdlib>
#include      <fstream>
#include      <iomanip>
#include      <iostream>
#include      <iterator>
#include      <limits>
#include      <list>
#include      <map>
#include      <queue>
#include      <set>
#include      <sstream>
#include      <vector>
#define endl '\n'
#define each(c, e) for (typeof(c.begin()) e = c.begin(); e != c.end(); ++e)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;

template<typename T1, typename T2> ostream& operator<<(ostream &o, const pair<T1, T2> &p) {return o << '(' << p.first << ", " << p.second << ')';}
template<typename I> ostream& print(ostream &o, I s, I e, int w = 5, int prec = 2, const string &sep = ", ", const string &lhs = "", const string &rhs = "") {
	o << lhs;
	if (s != e) o << setw(w) << setprecision(prec) << *(s++);
	for (; s != e; ++s) o << sep << setw(w) << setprecision(prec) << *s;
	return o << rhs;
}
template<typename T, template<typename E, typename A=std::allocator<E> > class C>
ostream& operator<<(ostream &o, const C<T>& c) {return print(o, c.begin(), c.end(), 0, 2, ", ", "[", "]");}
template<typename T, template<typename E, typename Compare = less<E>, typename Alloc = allocator<E> > class C>
ostream& operator<<(ostream &o, const C<T>& c) {return print(o, c.begin(), c.end(), 0, 2, ", ", "{", "}");}
template<typename K, typename T, template<typename E1, typename E2, typename Compare = std::less<E1>, class Allocator = std::allocator<std::pair<const E1, E2> > > class C>
ostream& operator<<(ostream &o, const C<K, T>& c) {return print(o, c.begin(), c.end(), 0, 2, ", ", "{", "}");}

// #define DEBUG
#ifndef DEBUG
#define cerr if (false) cout
#endif

const ll oo = numeric_limits<ll>::max() / 10;

struct Node {
	ll volume, val, lazy, mi, ma, agg;
	Node *left, *right;
	Node(ll volume, ll val = -1, ll lazy = -1) : volume(volume), val(val), lazy(lazy), agg(-1), left(0), right(0) {;}
	bool operator<(const Node &o) const { return volume < o.volume; }
	friend ostream& operator<<(ostream &os, const Node &n) { return os << n.volume << " [" << n.mi << ", " << n.ma << ")" << ", " << n.val << ", " << n.lazy; }
};
vector<Node> tree;

void print(Node *n, int ind = 0) {
#ifdef DEBUG
	if (!n) return;
	for (int i = 0; i < ind * 2; i += 1) cerr << " "; cerr << *n << endl;
	print(n->left, ind + 1), print(n->right, ind + 1);
#endif
}

Node* construct(int start, int end) {
	if (start == end) return NULL;
	const int mid = start + (end - start) / 2;
	tree[mid].left = construct(start, mid);
	tree[mid].mi = min(tree[mid].volume, tree[mid].left ? tree[mid].left->mi : +oo);
	tree[mid].right = construct(mid + 1, end);
	tree[mid].ma = max(tree[mid].volume + 1, tree[mid].right ? tree[mid].right->ma : -oo);
	return &tree[mid];
}

void update(Node *n, int query_start, int query_end, ll val) {
	if (!n || query_start >= n->ma || n->mi >= query_end) return;

	if (query_start <= n->volume && n->volume <= query_end) {
		n->agg = max(n->agg, n->val = max(n->val, val));
	}

	if (query_start <= n->mi && n->ma <= query_end) {
		n->agg = max(n->agg, n->lazy = max(n->lazy, val));
		return;
	}

	update(n->left, query_start, query_end, max(n->lazy, val));
	update(n->right, query_start, query_end, max(n->lazy, val));
	n->lazy = -1;
	if (n->left) n->agg = max(n->agg, n->left->agg);
	if (n->right) n->agg = max(n->agg, n->right->agg);
}

ll query(Node *n, int query_start, int query_end) {
	if (!n || query_start >= n->ma || n->mi >= query_end) return -oo;

	if (n->lazy != -1) {
		if (n->left) update(n->left, n->left->mi, n->left->ma, n->lazy);
		if (n->right) update(n->right, n->right->mi, n->right->ma, n->lazy);
		n->lazy = -1;
	}

	if (query_start <= n->mi && n->ma <= query_end) return n->agg;

	ll rtn = (query_start <= n->volume && n->volume <= query_end) ? n->val : -oo;
	// if (query_start <= n->mi && n->ma <= query_end) return max(rtn, n->agg);

	return max(rtn,
			max(
				query(n->left, query_start, query_end),
				query(n->right, query_start, query_end)));
}

int main() {
	int N;
	cin >> N;

	vector<ll> V(N);
	{
		set<ll> in_tree;
		for (int i = 0; i < N; i += 1) {
			ll r, h;
			cin >> r >> h;
			V[i] = r * r * h;
			if (!in_tree.count(V[i])) {
				tree.push_back(Node(V[i]));
				in_tree.insert(V[i]);
			}
		}
	}

	sort(tree.begin(), tree.end());
	Node *root = construct(0, tree.size());

	vector<ll> DP(N);
	for (int i = 0; i < N; i += 1) {
		cerr << "# querieng [" << 0 << ", " << V[i] << ")" << endl;
		DP[i] = max(V[i], query(root, 0, V[i]) + V[i]);
		print(root);

		cerr << "# updating [" << V[i] << ", " << tree.rbegin()->volume + 1 << ") to " << DP[i] << endl;
		update(root, V[i], tree.rbegin()->volume + 1, DP[i]);
		print(root);
	}

	cout << fixed << setprecision(20) << *max_element(DP.begin(), DP.end()) * acos(-1) << endl;

	return 0;
}


#include      <algorithm>
#include      <cmath>
#include      <cstdarg>
#include      <cstdio>
#include      <cstdlib>
#include      <fstream>
#include      <iomanip>
#include      <iostream>
#include      <iterator>
#include      <limits>
#include      <list>
#include      <map>
#include      <queue>
#include      <set>
#include      <sstream>
#include      <vector>
#define endl '\n'
#define each(c, e) for (typeof(c.begin()) e = c.begin(); e != c.end(); ++e)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;

template<typename T1, typename T2> ostream& operator<<(ostream &o, const pair<T1, T2> &p) {return o << '(' << p.first << ", " << p.second << ')';}
template<typename I> ostream& print(ostream &o, I s, I e, int w = 5, int prec = 2, const string &sep = ", ", const string &lhs = "", const string &rhs = "") {
	o << lhs;
	if (s != e) o << setw(w) << setprecision(prec) << *(s++);
	for (; s != e; ++s) o << sep << setw(w) << setprecision(prec) << *s;
	return o << rhs;
}
template<typename T, template<typename E, typename A=std::allocator<E> > class C>
ostream& operator<<(ostream &o, const C<T>& c) {return print(o, c.begin(), c.end(), 0, 2, ", ", "[", "]");}
template<typename T, template<typename E, typename Compare = less<E>, typename Alloc = allocator<E> > class C>
ostream& operator<<(ostream &o, const C<T>& c) {return print(o, c.begin(), c.end(), 0, 2, ", ", "{", "}");}
template<typename K, typename T, template<typename E1, typename E2, typename Compare = std::less<E1>, class Allocator = std::allocator<std::pair<const E1, E2> > > class C>
ostream& operator<<(ostream &o, const C<K, T>& c) {return print(o, c.begin(), c.end(), 0, 2, ", ", "{", "}");}

// #define cerr if (false) cout

const ll oo = numeric_limits<ll>::max() / 10;

struct Node {
	ll volume, val, lazy, mi, ma, agg;
	Node *left, *right;
	Node(ll volume, ll val = -1, ll lazy = -1) : volume(volume), val(val), lazy(lazy), agg(-1), left(0), right(0) {;}
	bool operator<(const Node &o) const { return volume < o.volume; }
	friend ostream& operator<<(ostream &os, const Node &n) { return os << n.volume << " [" << n.mi << ", " << n.ma << ")" << ", " << n.val << ", " << n.lazy; }
};
vector<Node> tree;

void print(Node *n, int ind = 0) {
	if (!n) return;
	for (int i = 0; i < ind * 2; i += 1) cerr << " "; cerr << *n << endl;
	print(n->left, ind + 1), print(n->right, ind + 1);
}

Node* construct(int start, int end) {
	if (start == end) return NULL;
	const int mid = start + (end - start) / 2;
	tree[mid].left = construct(start, mid);
	tree[mid].mi = min(tree[mid].volume, tree[mid].left ? tree[mid].left->mi : +oo);
	tree[mid].right = construct(mid + 1, end);
	tree[mid].ma = max(tree[mid].volume + 1, tree[mid].right ? tree[mid].right->ma : -oo);
	return &tree[mid];
}

void update(Node *n, int query_start, int query_end, ll val) {
	if (!n || query_start >= n->ma || n->mi >= query_end) return;

	if (query_start <= n->volume && n->volume <= query_end) {
		n->val = max(n->val, val);
		n->agg = max(n->agg, val);
	}

	if (query_start <= n->mi && n->ma <= query_end) {
		n->lazy = max(n->lazy, val);
		n->agg = max(n->agg, val);
		return;
	}

	update(n->left, query_start, query_end, max(n->lazy, val));
	update(n->right, query_start, query_end, max(n->lazy, val));
	n->lazy = -1;
	if (n->left) n->agg = max(n->agg, n->left->agg);
	if (n->right) n->agg = max(n->agg, n->right->agg);
}

ll query(Node *n, int query_start, int query_end) {
	if (!n || query_start >= n->ma || n->mi >= query_end) return -oo;

	if (n->lazy != -1) {
		update(n->left, query_start, query_end, n->lazy);
		update(n->right, query_start, query_end, n->lazy);
	}

	if (query_start <= n->mi && n->ma <= query_end) return n->agg;

	ll rtn = (query_start <= n->volume && n->volume <= query_end) ? n->val : -oo;
	// if (query_start <= n->mi && n->ma <= query_end) return max(rtn, n->agg);

	return max(rtn,
			max(
				query(n->left, query_start, query_end),
				query(n->right, query_start, query_end)));
}

int main() {
	int N;
	cin >> N;

	vector<ll> V(N);
	{
		set<ll> in_tree;
		for (int i = 0; i < N; i += 1) {
			ll r, h;
			cin >> r >> h;
			V[i] = r * r * h;
			if (!in_tree.count(V[i])) {
				tree.push_back(Node(V[i]));
				in_tree.insert(V[i]);
			}
		}
	}

	sort(tree.begin(), tree.end());
	Node *root = construct(0, tree.size());

	vector<ll> DP(N);
	DP[0] = V[0];
	cerr << "# updating [" << V[0] << ", " << tree.rbegin()->volume + 1 << ") to " << DP[0] << endl;
	update(root, V[0], tree.rbegin()->volume + 1, DP[0]);
	print(root);

	for (int i = 1; i < N; i += 1) {
		vector<ll>::const_iterator it = upper_bound(V.begin(), V.end(), V[i] - 1);
		ll on_other = -1;
		if (it != V.begin()) {
			cerr << "# querieng [" << 0 << ", " << V[i] << ")" << endl;
			on_other = query(root, 0, V[i]) + V[i];
			print(root);
		}
		DP[i] = max(V[i], on_other);

		cerr << "# updating [" << V[i] << ", " << tree.rbegin()->volume + 1 << ") to " << DP[i] << endl;
		update(root, V[i], tree.rbegin()->volume + 1, DP[i]);
		print(root);
	}

	cout << fixed << setprecision(20) << *max_element(DP.begin(), DP.end()) * acos(-1) << endl;

	return 0;
}


#include      <algorithm>
#include      <cmath>
#include      <cstdarg>
#include      <cstdio>
#include      <cstdlib>
#include      <fstream>
#include      <iomanip>
#include      <iostream>
#include      <iterator>
#include      <limits>
#include      <list>
#include      <map>
#include      <queue>
#include      <set>
#include      <sstream>
#include      <vector>
#define endl '\n'
#define each(c, e) for (typeof(c.begin()) e = c.begin(); e != c.end(); ++e)
using namespace std;
typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;

template<typename T1, typename T2> ostream& operator<<(ostream &o, const pair<T1, T2> &p) {return o << '(' << p.first << ", " << p.second << ')';}
template<typename I> ostream& print(ostream &o, I s, I e, int w = 5, int prec = 2, const string &sep = ", ", const string &lhs = "", const string &rhs = "") {
	o << lhs;
	if (s != e) o << setw(w) << setprecision(prec) << *(s++);
	for (; s != e; ++s) o << sep << setw(w) << setprecision(prec) << *s;
	return o << rhs;
}
template<typename T, template<typename E, typename A=std::allocator<E> > class C>
ostream& operator<<(ostream &o, const C<T>& c) {return print(o, c.begin(), c.end(), 0, 2, ", ", "[", "]");}
template<typename T, template<typename E, typename Compare = less<E>, typename Alloc = allocator<E> > class C>
ostream& operator<<(ostream &o, const C<T>& c) {return print(o, c.begin(), c.end(), 0, 2, ", ", "{", "}");}
template<typename K, typename T, template<typename E1, typename E2, typename Compare = std::less<E1>, class Allocator = std::allocator<std::pair<const E1, E2> > > class C>
ostream& operator<<(ostream &o, const C<K, T>& c) {return print(o, c.begin(), c.end(), 0, 2, ", ", "{", "}");}

const ll oo = numeric_limits<ll>::max() / 10;

int main() {
	ios_base::sync_with_stdio(false), cin.tie(0);
	int N;
	cin >> N;

	vector<ll> V(N);
	for (int i = 0; i < N; i += 1) {
		ll r, h;
		cin >> r >> h;
		V[i] = r * r * h;
	}

	vector<ll> DP(N);

	vector<pair<ll, ll> > inc_v;

	// inc_v.push_back(make_pair(5, 0));
	// inc_v.push_back(make_pair(6, 1));
	// inc_v.push_back(make_pair(8, 2));
	// cout << (--upper_bound(inc_v.begin(), inc_v.end(), make_pair(5 - 1ll, +oo)))->first << endl;
	// return 0;

	inc_v.push_back(make_pair(V[0], 0ll));

	for (int i = 1; i < N; i += 1) {
		vector<pair<ll, ll> >::const_iterator it = upper_bound(inc_v.begin(), inc_v.end(), make_pair(V[i] - 1, +oo));
		ll on_other = -oo;
		if (it != inc_v.begin()) on_other = DP[(--it)->second] + V[i];
		ll on_floor = V[i];
		ll not_placed = DP[i - 1];

		if (not_placed < on_floor || not_placed < on_other) {
			// cout << "Before: " << inc_v << ", trying to insert: " << V[i] << endl;
			while (!inc_v.empty() && V[i] <= inc_v.rbegin()->first) inc_v.pop_back();
			inc_v.push_back(make_pair(V[i], i));
			// cout << "After: " << inc_v << endl;
		}
		DP[i] = max(max(on_other, on_floor), not_placed);
	}

	cout << fixed << setprecision(20) << DP[N - 1] * acos(-1) << endl;

	return 0;
}


#define HEADER_H
//#define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
#define REP(i,n)	for(auto i=decltype(n)(0); i<(n); ++i)
#define all(v)		begin(v), end(v)
using namespace std;		using ull= unsigned long long;
using ll = long long;		using ld = long double;
using vi = vector<ll>;		using vvi= vector<vi>;
using vb = vector<bool>;	using ii = pair<ll,ll>;
constexpr bool LOG = true;
void Log() { if(LOG) cerr << "\n"; }
template<class T, class... S> void Log(T t, S... s){
	if(LOG) cerr << t << "\t", Log(s...);
} /* ============== END OF HEADER ============== */

ld pi = 3.1415926535;

int main(){
	ios_base::sync_with_stdio(false); cin.tie(nullptr);
	ll n; cin >> n;
	// map top radius to volume
	map<ll,ll> m;
	m[0] = 0;
	ll ans = 0;
	REP(i,n){
		ll r,h; cin >> r >> h;
		auto it = m.lower_bound(r);
		auto p = prev(it);
		ll vol = p->second + r*r*h;
		ans = max(ans, vol);
		m.insert(it,{r,vol});
		while(it!=m.end() && it->second <= vol){
			p = next(it);
			m.erase(it);
			it = p;
		}
	}

	cout << setprecision(15) <<pi * ans << endl;

	return 0;
}


#define HEADER_H
//#define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
#define REP(i,n)	for(auto i=decltype(n)(0); i<(n); ++i)
#define all(v)		begin(v), end(v)
using namespace std;		using ull= unsigned long long;
using ll = long long;		using ld = long double;
using vi = vector<ll>;		using vvi= vector<vi>;
using vb = vector<bool>;	using ii = pair<ll,ll>;
constexpr bool LOG = true;
void Log() { if(LOG) cerr << "\n"; }
template<class T, class... S> void Log(T t, S... s){
	if(LOG) cerr << t << "\t", Log(s...);
} /* ============== END OF HEADER ============== */

ld pi = 3.14159265358979;

int main(){
	ios_base::sync_with_stdio(false); cin.tie(nullptr);
	ll n; cin >> n;
	// map top radius to volume
	map<ll,ld> m;
	m[0] = 0;
	ld ans = 0;
	REP(i,n){
		ll r,h; cin >> r >> h;
		auto it = m.lower_bound(r*r*h);
		auto p = prev(it);
		ld vol = p->second + r*r*h;
		ans = max(ans, vol);
		if(it->first != r*r*h || vol > it->second)
			m[r*r*h] = vol;
		while(it!=m.end() && it->second <= vol){
			p = next(it);
			m.erase(it);
			it = p;
		}
	}

	cout <<fixed<< setprecision(15) <<pi * ans << endl;

	return 0;
}


#define HEADER_H
//#define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
#define REP(i,n)	for(auto i=decltype(n)(0); i<(n); ++i)
#define all(v)		begin(v), end(v)
using namespace std;		using ull= unsigned long long;
using ll = long long;		using ld = long double;
using vi = vector<ll>;		using vvi= vector<vi>;
using vb = vector<bool>;	using ii = pair<ll,ll>;
constexpr bool LOG = true;
void Log() { if(LOG) cerr << "\n"; }
template<class T, class... S> void Log(T t, S... s){
	if(LOG) cerr << t << "\t", Log(s...);
} /* ============== END OF HEADER ============== */

ld pi = 3.14159265358979;

int main(){
	ios_base::sync_with_stdio(false); cin.tie(nullptr);
	ll n; cin >> n;
	// map top radius to volume
	map<ll,ld> m;
	m[0] = 0;
	ld ans = 0;
	REP(i,n){
		ll r,h; cin >> r >> h;
		auto it = m.lower_bound(r*r*h);
		auto p = prev(it);
		ld vol = p->second + r*r*h;
		ans = max(ans, vol);
		if(it->first != r*r*h || vol > it->second)
			m.emplace_hint(it, r*r*h, vol);
		while(it!=m.end() && it->second <= vol){
			p = next(it);
			m.erase(it);
			it = p;
		}
	}

	cout <<fixed<< setprecision(15) <<pi * ans << endl;

	return 0;
}


#define HEADER_H
//#define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
#define REP(i,n)	for(auto i=decltype(n)(0); i<(n); ++i)
#define all(v)		begin(v), end(v)
using namespace std;		using ull= unsigned long long;
using ll = long long;		using ld = long double;
using vi = vector<ll>;		using vvi= vector<vi>;
using vb = vector<bool>;	using ii = pair<ll,ll>;
constexpr bool LOG = true;
void Log() { if(LOG) cerr << "\n"; }
template<class T, class... S> void Log(T t, S... s){
	if(LOG) cerr << t << "\t", Log(s...);
} /* ============== END OF HEADER ============== */

ld pi = 3.1415926535;

int main(){
	ios_base::sync_with_stdio(false); cin.tie(nullptr);
	ll n; cin >> n;
	// map top radius to volume
	map<ll,ld> m;
	m[0] = 0;
	ld ans = 0;
	REP(i,n){
		ll r,h; cin >> r >> h;
		auto it = m.lower_bound(r*h*h);
		auto p = prev(it);
		ld vol = p->second + r*r*h;
		ans = max(ans, vol);
		m.insert(it,{r*h*h,vol});
		while(it!=m.end() && it->second <= vol){
			p = next(it);
			m.erase(it);
			it = p;
		}
	}

	cout << setprecision(15) <<pi * ans << endl;

	return 0;
}


#define HEADER_H
//#define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
#define REP(i,n)	for(auto i=decltype(n)(0); i<(n); ++i)
#define all(v)		begin(v), end(v)
using namespace std;		using ull= unsigned long long;
using ll = long long;		using ld = long double;
using vi = vector<ll>;		using vvi= vector<vi>;
using vb = vector<bool>;	using ii = pair<ll,ll>;
constexpr bool LOG = true;
void Log() { if(LOG) cerr << "\n"; }
template<class T, class... S> void Log(T t, S... s){
	if(LOG) cerr << t << "\t", Log(s...);
} /* ============== END OF HEADER ============== */

ld pi = 3.1415926535;

int main(){
	ios_base::sync_with_stdio(false); cin.tie(nullptr);
	ll n; cin >> n;
	// map top radius to volume
	map<ll,ld> m;
	m[0] = 0;
	ld ans = 0;
	REP(i,n){
		ll r,h; cin >> r >> h;
		auto it = m.lower_bound(r*r*h);
		auto p = prev(it);
		ld vol = p->second + r*r*h;
		ans = max(ans, vol);
		m.insert(it,{r*h*h,vol});
		while(it!=m.end() && it->second <= vol){
			p = next(it);
			m.erase(it);
			it = p;
		}
	}

	cout << setprecision(15) <<pi * ans << endl;

	return 0;
}


#define HEADER_H
//#define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
#define REP(i,n)	for(auto i=decltype(n)(0); i<(n); ++i)
#define all(v)		begin(v), end(v)
using namespace std;		using ull= unsigned long long;
using ll = long long;		using ld = long double;
using vi = vector<ll>;		using vvi= vector<vi>;
using vb = vector<bool>;	using ii = pair<ll,ll>;
constexpr bool LOG = true;
void Log() { if(LOG) cerr << "\n"; }
template<class T, class... S> void Log(T t, S... s){
	if(LOG) cerr << t << "\t", Log(s...);
} /* ============== END OF HEADER ============== */

ld pi = 3.14159265358979;

int main(){
	ios_base::sync_with_stdio(false); cin.tie(nullptr);
	ll n; cin >> n;
	// map top radius to volume
	map<ll,ld> m;
	m[0] = 0;
	ld ans = 0;
	REP(i,n){
		ll r,h; cin >> r >> h;
		auto it = m.lower_bound(r*r*h);
		auto p = prev(it);
		ld vol = p->second + r*r*h;
		ans = max(ans, vol);
		m.insert(it,{r*r*h,vol});
		while(it!=m.end() && it->second <= vol){
			p = next(it);
			m.erase(it);
			it = p;
		}
	}

	cout <<fixed<< setprecision(15) <<pi * ans << endl;

	return 0;
}


#define HEADER_H
//#define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
#define REP(i,n)	for(auto i=decltype(n)(0); i<(n); ++i)
#define all(v)		begin(v), end(v)
using namespace std;		using ull= unsigned long long;
using ll = long long;		using ld = long double;
using vi = vector<ll>;		using vvi= vector<vi>;
using vb = vector<bool>;	using ii = pair<ll,ll>;
constexpr bool LOG = true;
void Log() { if(LOG) cerr << "\n"; }
template<class T, class... S> void Log(T t, S... s){
	if(LOG) cerr << t << "\t", Log(s...);
} /* ============== END OF HEADER ============== */

ld pi = 3.14159265358979;

int main(){
	ios_base::sync_with_stdio(false); cin.tie(nullptr);
	ll n; cin >> n;
	// map top radius to volume
	map<ll,ll> m;
	m[0] = 0;
	ll ans = 0;
	REP(i,n){
		ll r,h; cin >> r >> h;
		auto it = m.lower_bound(r*r*h);
		auto p = prev(it);
		ll vol = p->second + r*r*h;
		ans = max(ans, vol);
		if(it->first == r*r*h){
			if(it->second < vol) it->second = vol;
		} else
			m.insert(it, {r*r*h, vol});
		while(it!=m.end() && it->second <= vol)
			it = m.erase(it);
	}

	cout <<fixed<< setprecision(15) <<pi * ans << endl;

	return 0;
}


#define HEADER_H
//#define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
#define REP(i,n)	for(auto i=decltype(n)(0); i<(n); ++i)
#define all(v)		begin(v), end(v)
using namespace std;		using ull= unsigned long long;
using ll = long long;		using ld = long double;
using vi = vector<ll>;		using vvi= vector<vi>;
using vb = vector<bool>;	using ii = pair<ll,ll>;
constexpr bool LOG = true;
void Log() { if(LOG) cerr << "\n"; }
template<class T, class... S> void Log(T t, S... s){
	if(LOG) cerr << t << "\t", Log(s...);
} /* ============== END OF HEADER ============== */

ld pi = 3.1415926535;

int main(){
	ios_base::sync_with_stdio(false); cin.tie(nullptr);
	ll n; cin >> n;
	// map top radius to volume
	map<ll,ld> m;
	m[0] = 0;
	ld ans = 0;
	REP(i,n){
		ll r,h; cin >> r >> h;
		auto it = m.lower_bound(r*r*h);
		auto p = prev(it);
		ld vol = p->second + r*r*h;
		ans = max(ans, vol);
		m.insert(it,{r*r*h,vol});
		while(it!=m.end() && it->second <= vol){
			p = next(it);
			m.erase(it);
			it = p;
		}
	}

	cout << setprecision(15) <<pi * ans << endl;

	return 0;
}


#define HEADER_H
//#define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
#define REP(i,n)	for(auto i=decltype(n)(0); i<(n); ++i)
#define all(v)		begin(v), end(v)
using namespace std;		using ull= unsigned long long;
using ll = long long;		using ld = long double;
using vi = vector<ll>;		using vvi= vector<vi>;
using vb = vector<bool>;	using ii = pair<ll,ll>;
constexpr bool LOG = true;
void Log() { if(LOG) cerr << "\n"; }
template<class T, class... S> void Log(T t, S... s){
	if(LOG) cerr << t << "\t", Log(s...);
} /* ============== END OF HEADER ============== */

ld pi = 3.1415926535;

int main(){
	ios_base::sync_with_stdio(false); cin.tie(nullptr);
	ll n; cin >> n;
	// map top radius to volume
	map<ll,ld> m;
	m[0] = 0;
	ld ans = 0;
	REP(i,n){
		ll r,h; cin >> r >> h;
		auto it = m.lower_bound(r);
		auto p = prev(it);
		ld vol = p->second + r*r*h;
		ans = max(ans, vol);
		m.insert(it,{r,vol});
		while(it!=m.end() && it->second <= vol){
			p = next(it);
			m.erase(it);
			it = p;
		}
	}

	cout << setprecision(15) <<pi * ans << endl;

	return 0;
}


#define HEADER_H
//#define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
#define REP(i,n)	for(auto i=decltype(n)(0); i<(n); ++i)
#define all(v)		begin(v), end(v)
using namespace std;		using ull= unsigned long long;
using ll = long long;		using ld = long double;
using vi = vector<ll>;		using vvi= vector<vi>;
using vb = vector<bool>;	using ii = pair<ll,ll>;
constexpr bool LOG = true;
void Log() { if(LOG) cerr << "\n"; }
template<class T, class... S> void Log(T t, S... s){
	if(LOG) cerr << t << "\t", Log(s...);
} /* ============== END OF HEADER ============== */

ld pi = 3.1415926535;

int main(){
	ios_base::sync_with_stdio(false); cin.tie(nullptr);
	ll n; cin >> n;
	// map top radius to volume
	map<ll,ll> m;
	m[0] = 0;
	ll ans = 0;
	REP(i,n){
		ll r,h; cin >> r >> h;
		auto it = m.lower_bound(r);
		auto p = prev(it);
		Log("build on",p->first, p->second);
		ll vol = p->second + r*r*h;
		ans = max(ans, vol);
		Log("insert",r,vol);
		m.insert(it,{r,vol});
		while(it->second <= vol){
			it = m.erase(it);
		}
	}

	cout << setprecision(15) <<pi * ans << endl;

	return 0;
}


#define HEADER_H
//#define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
#define REP(i,n)	for(auto i=decltype(n)(0); i<(n); ++i)
#define all(v)		begin(v), end(v)
using namespace std;		using ull= unsigned long long;
using ll = long long;		using ld = long double;
using vi = vector<ll>;		using vvi= vector<vi>;
using vb = vector<bool>;	using ii = pair<ll,ll>;
constexpr bool LOG = true;
void Log() { if(LOG) cerr << "\n"; }
template<class T, class... S> void Log(T t, S... s){
	if(LOG) cerr << t << "\t", Log(s...);
} /* ============== END OF HEADER ============== */

ld pi = 3.14159265358979;

int main(){
	ios_base::sync_with_stdio(false); cin.tie(nullptr);
	ll n; cin >> n;
	// map top radius to volume
	map<ll,ld> m;
	m[0] = 0;
	ld ans = 0;
	REP(i,n){
		ll r,h; cin >> r >> h;
		auto it = m.lower_bound(r*r*h);
		auto p = prev(it);
		ld vol = p->second + r*r*h;
		ans = max(ans, vol);
		if(it->first != r*r*h || vol > it->second)
			m.insert(it,{r*r*h,vol});
		while(it!=m.end() && it->second <= vol){
			p = next(it);
			m.erase(it);
			it = p;
		}
	}

	cout <<fixed<< setprecision(15) <<pi * ans << endl;

	return 0;
}


#define HEADER_H
//#define _GLIBCXX_DEBUG
#include <bits/stdc++.h>
#define REP(i,n)	for(auto i=decltype(n)(0); i<(n); ++i)
#define all(v)		begin(v), end(v)
using namespace std;		using ull= unsigned long long;
using ll = long long;		using ld = long double;
using vi = vector<ll>;		using vvi= vector<vi>;
using vb = vector<bool>;	using ii = pair<ll,ll>;
constexpr bool LOG = true;
void Log() { if(LOG) cerr << "\n"; }
template<class T, class... S> void Log(T t, S... s){
	if(LOG) cerr << t << "\t", Log(s...);
} /* ============== END OF HEADER ============== */

ld pi = 3.14159265358979;

int main(){
	ios_base::sync_with_stdio(false); cin.tie(nullptr);
	ll n; cin >> n;
	// map top radius to volume
	map<ll,ll> m;
	m[0] = 0;
	ll ans = 0;
	REP(i,n){
		ll r,h; cin >> r >> h;
		auto it = m.lower_bound(r*r*h);
		auto p = prev(it);
		ll vol = p->second + r*r*h;
		ans = max(ans, vol);
		if(it->first == r*r*h){
			if(it->second < vol) it->second = vol;
			++it;
		} else
			m.insert(it, {r*r*h, vol});
		while(it!=m.end() && it->second <= vol)
			it = m.erase(it);
	}

	cout <<fixed<< setprecision(15) <<pi * ans << endl;

	return 0;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <functional>
#include <string>
#include <iomanip>      // std::setprecision

using namespace std;
#define ___ ios_base::sync_with_stdio(false); cin.tie(NULL);

using ll = long long;
using namespace std;

int n;
vector <pair<ll,int>> arr;
ll q[100001*4];
ll dp[100001];

void update(int idx, ll x, int id = 1, int b = 0, int e = n) {
	if (idx < b || idx >= e) return;
	if (idx == b && e - b == 1) {
		q[id] = x;
		return;
	}
	int mid = (b + e) / 2 , 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) / 2, l = id << 1, r = l | 1;
	return max(query(ql, qr, l, b, mid), query(ql, qr, r, mid, e));
}

int main()
{
	___

	cin >> n;
	arr.resize(n);
	for (int i = 0; i < n;++i)
	{
		ll t1, t2;
		cin >> t1 >> t2;
		arr[i].first = t1*t1*t2;
		arr[i].second = -i;
	}
	sort(arr.begin(), arr.end());

	for (int i = 0; i < n; ++i)
	{
		auto ix = -arr[i].second;
		auto val = arr[i].first;
		dp[ix] = query(0, ix) + val;
		update(ix, dp[ix]);

	}
	cout << fixed << setprecision((6)) << double(query(0, n)) * acos(-1.0)<< endl;

}


#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <functional>
#include <string>
#include <iomanip>      // std::setprecision

using namespace std;
#define ___ ios_base::sync_with_stdio(false); cin.tie(NULL);

using ll = long long;
using namespace std;

int n;
vector <pair<ll,int>> arr;
ll q[100001];
ll dp[100001];

void update(int idx, ll 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 main()
{
	___

	cin >> n;
	arr.resize(n);
	for (int i = 0; i < n;++i)
	{
		ll t1, t2;
		cin >> t1 >> t2;
		arr[i].first = t1*t1*t2;
		arr[i].second = -i;
	}
	sort(arr.begin(), arr.end());

	for (int i = 0; i < n; ++i)
	{
		auto ix = -arr[i].second;
		auto val = arr[i].first;
		dp[ix] = query(0, ix) + val;
		update(ix, dp[ix]);

	}
	cout << fixed << setprecision((6)) << double(query(0, n)) * acos(-1.0)<< endl;

}


#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <functional>
#include <string>
#include <iomanip>      // std::setprecision

using namespace std;
#define ___ ios_base::sync_with_stdio(false); cin.tie(NULL);

using ll = long long;
using namespace std;

int n;
vector <pair<ll,int>> arr;
ll q[100001*4];
ll dp[100001];

void update(int idx, ll 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 main()
{
	___

	cin >> n;
	arr.resize(n);
	for (int i = 0; i < n;++i)
	{
		ll t1, t2;
		cin >> t1 >> t2;
		arr[i].first = t1*t1*t2;
		arr[i].second = -i;
	}
	sort(arr.begin(), arr.end());

	for (int i = 0; i < n; ++i)
	{
		auto ix = -arr[i].second;
		auto val = arr[i].first;
		dp[ix] = query(0, ix) + val;
		update(ix, dp[ix]);

	}
	cout << fixed << setprecision((6)) << double(query(0, n)) * acos(-1.0)<< endl;

}


#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <functional>
#include <string>
#include <iomanip>      // std::setprecision

using namespace std;
#define io_faster() ios_base::sync_with_stdio(false); cin.tie(NULL);

using ll = long long;
vector<ll> arr;
vector<ll> table;
int n;
auto PI = acos(-1);
ll _max = 0;
ll solve(int i)
{
	auto &ret = table[i];
	if (ret > 0)return ret;
	if (ret >= n) return 0;
	ret = 0;
	for (int j = i + 1; j < n; ++j)
	{
		if (solve(j) > arr[i] && arr[j] > arr[i])
			ret = max(ret, solve(j));
	}

	ret = ret + arr[i];
	_max = max(_max, ret);
	return ret;
}
int main()
{
	cin >> n;
	arr.resize(n);
	table.resize(n, -1);
	for (int i = 0; i < n; ++i)
	{
		int t1, t2;
		scanf("%d", &t1);
		scanf("%d", &t2);
		//cin >> arr[i];
		arr[i] =ll( t1*t1*t2);
	}
	if (n > 50000)
		printf("IDOL");
	solve(0);
	std::cout << std::fixed<< std::setprecision(6)<< _max *  PI << endl;

}


#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <functional>
#include <string>
#include <iomanip>      // std::setprecision

using namespace std;
#define io_faster() ios_base::sync_with_stdio(false); cin.tie(NULL);

using ll = long long;
vector<ll> arr;
vector<ll> table;
int n;
auto PI = acos(-1);
ll _max = 0;
ll solve(int i)
{
	auto &ret = table[i];
	if (ret > 0)return ret;
	if (ret >= n) return 0;
	ret = 0;
	for (int j = i + 1; j < n; ++j)
	{
		if (solve(j) > arr[i] && arr[j] > arr[i])
			ret = max(ret, solve(j));
	}

	ret = ret + arr[i];
	_max = max(_max, ret);
	return ret;
}
int main()
{
	io_faster();
	cin >> n;
	arr.resize(n);
	table.resize(n, -1);
	for (int i = 0; i < n; ++i)
	{
		int t1, t2;
		scanf("%d", &t1);
		scanf("%d", &t2);
		//cin >> arr[i];
		arr[i] = t1*t1*t2;
	}
	if (n > 50000)
		printf("IDOL");
	solve(0);
	std::cout << std::fixed<< std::setprecision(6)<< _max *  PI << endl;

}


#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <functional>
#include <string>
#include <iomanip>      // std::setprecision

using namespace std;
#define io_faster() ios_base::sync_with_stdio(false); cin.tie(NULL);

using ll = long long;
vector<ll> arr;
vector<ll> table;
int n;
auto PI = acos(-1);
ll _max = 0;
ll solve(int i)
{
	auto &ret = table[i];
	if (ret > 0)return ret;
	if (ret >= n) return 0;
	ret = 0;
	for (int j = i + 1; j < n; ++j)
	{
		if (solve(j) > arr[i] && arr[j] > arr[i])
			ret = max(ret, solve(j));
	}

	ret = ret + arr[i];
	_max = max(_max, ret);
	return ret;
}
int main()
{
	io_faster();
	cin >> n;
	arr.resize(n);
	table.resize(n, -1);
	for (int i = 0; i < n; ++i)
	{
		ll t1, t2;
		cin >> t1 >> t2;
		//cin >> arr[i];
		arr[i] = t1*t1*t2;
	}
	solve(0);
	std::cout << std::fixed<< std::setprecision(6)<< _max *  PI << endl;

}


#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <functional>
#include <string>
#include <iomanip>      // std::setprecision

using namespace std;
#define io_faster() ios_base::sync_with_stdio(false); cin.tie(NULL);

using ll = long long;
vector<ll> arr;
vector<ll> table;
int n;
auto PI = acos(-1);
ll _max = 0;
ll solve(int i)
{
	auto &ret = table[i];
	if (ret > 0)return ret;
	if (ret >= n) return 0;
	ret = 0;
	for (int j = i + 1; j < n; ++j)
	{
		if (solve(j) > arr[i] && arr[j] > arr[i])
			ret = max(ret, solve(j));
	}

	ret = ret + arr[i];
	_max = max(_max, ret);
	return ret;
}
int main()
{
	cin >> n;
	arr.resize(n);
	table.resize(n, -1);
	for (int i = 0; i < n; ++i)
	{
		int t1, t2;
		scanf("%d", &t1);
		scanf("%d", &t2);
		//cin >> arr[i];
		arr[i] =ll( t1*t1*t2);
	}
	if (n > 50000) {
		printf("IDOL");
		return 0;
	}
	solve(0);
	std::cout << std::fixed<< std::setprecision(6)<< _max *  PI << endl;

}


#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <functional>
#include <string>
#include <iomanip>      // std::setprecision

using namespace std;
#define io_faster() ios_base::sync_with_stdio(false); cin.tie(NULL);

using ll = long long;
vector<ll> arr;
vector<ll> table;
int n;
auto PI = acos(-1);
ll solve(int i)
{
	auto &ret = table[i];
	if (ret > 0)return ret;
	if (ret >= n) return 0;
	ret = 0;
	for (int j = i + 1; j < n; ++j)
	{
		if (solve(j) > arr[i] && arr[j] > arr[i])
			ret = max(ret, solve(j));
	}

	return ret = ret + arr[i];
}
int main()
{

	cin >> n;
	arr.resize(n);
	table.resize(n, -1);
	for (int i = 0; i < n; ++i)
	{
		int t1, t2;
		cin >> t1 >> t2;
		arr[i] = t1*t1*t2;
	}
	solve(0);
	std::cout << std::fixed;
	std::cout << std::setprecision(6)<< table[0] * PI << endl;

}


#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>
#include <cstring>
#include <functional>
#include <list>
#include <unordered_map>
#include <map>
#include <array>
using namespace std;
using ll = long long;

using namespace std;
#define ___ ios_base::sync_with_stdio(false); cin.tie(NULL);
int n;
vector<double> arr;
double table[1001];
double PI = 3.14159265358979323846;

int main()
{

	___
		cin >> n;
	arr.resize(n);
	for (auto &i : arr)
	{
		double r, h;
		cin >> r >> h;
		i = r *r * h * PI;
	}
	for (int i = 0; i < n; ++i)
		table[i] = arr[i];
	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < i; ++j)
		{
			if (arr[i] > arr[j])
				table[i] = max(table[i], table[j] + arr[i]);
		}
	}

	printf("%lf\n", *max_element(table, table + 1001));

}


#include <iostream>
#include <cstdio>
#include <vector>
#include <algorithm>
#include <string>
#include <queue>
#include <cstring>
#include <functional>
#include <list>
#include <unordered_map>
#include <map>
#include <array>
using namespace std;
using ll = long long;

using namespace std;
#define ___ ios_base::sync_with_stdio(false); cin.tie(NULL);
int n;
vector<double> arr;
double table[100001];
double PI = 3.14159265358979323846;

int main()
{

	___
		cin >> n;
	arr.resize(n);
	for (auto &i : arr)
	{
		double r, h;
		cin >> r >> h;
		i = r *r * h * PI;
	}
	for (int i = 0; i < n; ++i)
		table[i] = arr[i];
	for (int i = 0; i < n; ++i)
	{
		for (int j = 0; j < i; ++j)
		{
			if (arr[i] > arr[j])
				table[i] = max(table[i], table[j] + arr[i]);
		}
	}

	printf("%lf\n", *max_element(table, table + 1001));

}


#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <functional>
#include <string>
#include <iomanip>      // std::setprecision

using namespace std;
#define io_faster() ios_base::sync_with_stdio(false); cin.tie(NULL);

using ll = long long;
vector<ll> arr;
vector<ll> table;
int n;
auto PI = acos(-1);
ll _max = 0;
ll solve(int i)
{
	auto &ret = table[i];
	if (ret > 0)return ret;
	if (ret >= n) return 0;
	ret = 0;
	for (int j = i + 1; j < n; ++j)
	{
		if (solve(j) > arr[i] && arr[j] > arr[i])
			ret = max(ret, solve(j));
	}
	ret += arr[i];
	_max = max(_max, ret);
	return ret;
}
int main()
{
	io_faster();
	cin >> n;
	arr.resize(n);
	table.resize(n, -1);
	for (int i = 0; i < n; ++i)
	{
		ll t1, t2;
		cin >> t1 >> t2;
		//cin >> arr[i];
		//arr[i] =// t1*t1*t2;
	}
	solve(0);
	std::cout << std::fixed;
	std::cout << std::setprecision(6)<< _max * PI << endl;

}


#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <functional>
#include <string>
#include <iomanip>      // std::setprecision

using namespace std;
#define io_faster() ios_base::sync_with_stdio(false); cin.tie(NULL);

using ll = long long;
vector<ll> arr;
vector<ll> table;
int n;
auto PI = acos(-1);
ll _max = 0;
ll solve(int i)
{
	auto &ret = table[i];
	if (ret > 0)return ret;
	if (ret >= n) return 0;
	ret = 0;
	for (int j = i + 1; j < n; ++j)
	{
		if (solve(j) > arr[i] && arr[j] > arr[i])
			ret = max(ret, solve(j));
	}

	ret = ret + arr[i];
	_max = max(_max, ret);
	return ret;
}
int main()
{
	io_faster();
	cin >> n;
	arr.resize(n);
	table.resize(n, -1);
	for (int i = 0; i < n; ++i)
	{
		int t1, t2;
		scanf("%d", &t1);
		scanf("%d", &t2);
		//cin >> arr[i];
		arr[i] =ll( t1*t1*t2);
	}
	if (n > 50000)
		printf("IDOL");
	solve(0);
	std::cout << std::fixed<< std::setprecision(6)<< _max *  PI << endl;

}


#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <functional>
#include <string>
#include <iomanip>      // std::setprecision

using namespace std;
#define io_faster() ios_base::sync_with_stdio(false); cin.tie(NULL);

using ll = long long;
vector<ll> arr;
vector<ll> table;
int n;
auto PI = acos(-1);
ll _max = 0;
ll solve(int i)
{
	auto &ret = table[i];
	if (ret > 0)return ret;
	if (ret >= n) return 0;
	ret = 0;
	for (int j = i + 1; j < n; ++j)
	{
		if (solve(j) > arr[i] && arr[j] > arr[i])
			ret = max(ret, solve(j));
	}

	ret = ret + arr[i];
	_max = max(_max, ret);
	return ret;
}
int main()
{
	io_faster();
	cin >> n;
	arr.resize(n);
	table.resize(n, -1);
	for (int i = 0; i < n; ++i)
	{
		ll t1, t2;
		cin >> t1 >> t2;
		//cin >> arr[i];
		arr[i] = t1*t1*t2;
	}
	if (n > 50000)
		printf("IDOL");
	solve(0);
	std::cout << std::fixed<< std::setprecision(6)<< _max *  PI << endl;

}


#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <functional>
#include <string>
#include <iomanip>      // std::setprecision

using namespace std;
#define io_faster() ios_base::sync_with_stdio(false); cin.tie(NULL);

using ll = long long;
vector<ll> arr;
vector<ll> table;
int n;
auto PI = acos(-1);
ll _max = 0;
ll solve(int i)
{
	auto &ret = table[i];
	if (ret > 0)return ret;
	if (ret >= n) return 0;
	ret = 0;
	for (int j = i + 1; j < n; ++j)
	{
		if (solve(j) > arr[i] && arr[j] > arr[i])
			ret = max(ret, solve(j));
	}
	ret += arr[i];
	_max = max(_max, ret);
	return ret;
}
int main()
{
	io_faster();
	cin >> n;
	arr.resize(n);
	table.resize(n, -1);
	for (int i = 0; i < n; ++i)
	{
		//int t1, t2;
		//cin >> t1 >> t2;
		cin >> arr[i];
		//arr[i] =// t1*t1*t2;
	}
	solve(0);
	//td::cout << std::fixed;
	//std::cout << std::setprecision(6)<< table[0] * PI << endl;
	cout << _max << endl;
}


#include <iostream>
#include <vector>
#include <algorithm>
#include <unordered_map>
#include <functional>
#include <string>
#include <iomanip>      // std::setprecision

using namespace std;
#define io_faster() ios_base::sync_with_stdio(false); cin.tie(NULL);

using ll = long long;
vector<ll> arr;
vector<ll> table;
int n;
auto PI = acos(-1);
ll _max = 0;
ll solve(int i)
{
	auto &ret = table[i];
	if (ret > 0)return ret;
	if (ret >= n) return 0;
	ret = 0;
	for (int j = i + 1; j < n; ++j)
	{
		if (solve(j) > arr[i] && arr[j] > arr[i])
			ret = max(ret, solve(j));
	}

	ret = ret + arr[i];
	_max = max(_max, ret);
	return ret;
}
int main()
{
	io_faster();
	cin >> n;
	arr.resize(n);
	table.resize(n, -1);
	for (int i = 0; i < n; ++i)
	{
		ll t1, t2;
		scanf("%ld", &t1);
		scanf("%ld", &t2);
		//cin >> arr[i];
		arr[i] = t1*t1*t2;
	}
	if (n > 50000)
		printf("IDOL");
	solve(0);
	std::cout << std::fixed<< std::setprecision(6)<< _max *  PI << endl;

}


/*********************************ENTER THE DRAGON**********************************/

#include <cstdio>
#include <iostream>
#include <cmath>
#include <string>
#include <list>
#include <vector>
#include <algorithm>
#include <functional>
#include <utility>
#include <set>
#include <map>
#include <complex>
#include <queue>
#include <stack>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <string.h>
#include <cassert>
#include <climits>
#include <iomanip>
using namespace std;

/************************************************************************************/

const int maxn = 100100;
pair<long double, int> a[maxn];
long double PI = acos(-1.0);
long double ST[4 * maxn], dp[maxn];

void constructST(int c, int s, int e) {
	if (s==e)
	{
		ST[c] = 0.0;
		return;
	}
	int m = (s + e) >> 1;
	constructST(c+c+1, s, m);
	constructST(c+c+2, m+1, e);
	ST[c] = 0.0;
	return;
}

void updateST(int c, int s, int e, int x, long double val) {
	 if(s == e) {
	 	  ST[c] = dp[s] = val;
	 	  return;
	 }
	 int mid = (s + e) >> 1;
	 if(x <= mid)
	    updateST(c+c+1, s, mid, x, val);
	 else
	    updateST(c+c+2, mid + 1, e, x, val);
	 {
	 	 ST[c] = max(ST[c+c+1], ST[c+c+2]);
	 }
	 return;
}

long double queryST(int c, int s, int e, int L, int R) {
	if(s > R || e < L || s > e) return 0.0;
	if(s >= L && e <= R) return ST[c];
	int mid = (s + e) >> 1;
	long double pp = queryST(c+c+1, s, mid, L, R);
	long double qq = queryST(c+c+2, mid + 1, e, L, R);
	return max(pp, qq);
}

int main()
{
   int n;
   scanf("%d", &n);
   for (int i = 0; i < n; i++) {
   	    long long x, y;
   	    scanf("%I64d %I64d", &x, &y);
   	    a[i].first = (long double)PI * x * x * y;
   	    a[i].second = -i;
   }
   sort(a, a + n);

   constructST(0, 0, n - 1);

   for (int i = 0; i < n; i++) {
   	    long double vol = a[i].first;
   	    int id = -a[i].second;
   	    long double Q = queryST(0, 0, n - 1, 0, id);
   	    dp[id] = Q + vol;
   	    updateST(0, 0, n - 1, id, dp[id]);
   }
   long double ans = queryST(0, 0, n - 1, 0, n - 1);
   cout << setprecision(20) << ans << endl;
   return 0;
}


/*********************************ENTER THE DRAGON**********************************/

#include <cstdio>
#include <iostream>
#include <cmath>
#include <string>
#include <list>
#include <vector>
#include <algorithm>
#include <functional>
#include <utility>
#include <set>
#include <map>
#include <complex>
#include <queue>
#include <stack>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <string.h>
#include <cassert>
#include <climits>
#include <iomanip>
using namespace std;

/************************************************************************************/

const int maxn = 100100;
long double a[maxn], b[maxn];
long double PI = acos(-1.0);
long double ST[4 * maxn], dp[maxn];

void constructST(int c, int s, int e) {
	if (s==e)
	{
		ST[c] = 0.0;
		return;
	}
	int m = (s + e) >> 1;
	constructST(c+c+1, s, m);
	constructST(c+c+2, m+1, e);
	ST[c] = 0.0;
	return;
}

void updateST(int c, int s, int e, int x, long double val) {
	 if(s == e) {
	 	  ST[c] = val;
	 	  return;
	 }
	 int mid = (s + e) >> 1;
	 if(x <= mid)
	    updateST(c+c+1, s, mid, x, val);
	 else
	    updateST(c+c+2, mid + 1, e, x, val);
	 {
	 	 ST[c] = max(ST[c+c+1], ST[c+c+2]);
	 }
	 return;
}

long double queryST(int c, int s, int e, int L, int R) {
	if(s > R || e < L || s > e) return 0.0;
	if(s >= L && e <= R) return ST[c];
	int mid = (s + e) >> 1;
	long double pp = queryST(c+c+1, s, mid, L, R);
	long double qq = queryST(c+c+2, mid + 1, e, L, R);
	return max(pp, qq);
}

int main()
{
   int n;
   scanf("%d", &n);
   for (int i = 0; i < n; i++) {
   	    long long x, y;
   	    scanf("%I64d %I64d", &x, &y);
   	    a[i] = (long double)PI * x * x * y;
   	    b[i] = a[i];
   }
   sort(b, b + n);
   map<long double, int> ID;
   int cnt = 0;
   for (int i = 0; i < n; i++)
		if ((i == 0) || (b[i] > b[i - 1]))
			ID[b[i]] = cnt++;

   constructST(0, 0, n - 1);
   long double ans = 0.0;
   for (int i = 0; i < n; i++) {
   	    int id = ID[ a[i] ];
   	    long double Q = queryST(0, 0, n - 1, 0, id - 1);
   	    dp[id] = Q + a[i];
   	    ans = max(ans, dp[id]);
   	    updateST(0, 0, n - 1, id, dp[id]);
   }

   cout << setprecision(20) << ans << endl;
   return 0;
}


/*********************************ENTER THE DRAGON**********************************/

#include <cstdio>
#include <iostream>
#include <cmath>
#include <string>
#include <list>
#include <vector>
#include <algorithm>
#include <functional>
#include <utility>
#include <set>
#include <map>
#include <complex>
#include <queue>
#include <stack>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <string.h>
#include <cassert>
#include <climits>
#include <iomanip>
using namespace std;

/************************************************************************************/

const int maxn = 100100;
pair<long double, int> a[maxn];
long double PI = acos(-1.0);
long double ST[4 * maxn], dp[maxn];

void constructST(int c, int s, int e) {
	if (s==e)
	{
		ST[c] = 0.0;
		return;
	}
	int m = (s + e) >> 1;
	constructST(c+c+1, s, m);
	constructST(c+c+2, m+1, e);
	ST[c] = 0.0;
	return;
}

void updateST(int c, int s, int e, int x, long double val) {
	 if(s == e) {
	 	  ST[c] = dp[s] = val;
	 	  return;
	 }
	 int mid = (s + e) >> 1;
	 if(x <= mid)
	    updateST(c+c+1, s, mid, x, val);
	 else
	    updateST(c+c+2, mid + 1, e, x, val);
	 {
	 	 ST[c] = max(ST[c+c+1], ST[c+c+2]);
	 }
	 return;
}

long double queryST(int c, int s, int e, int L, int R) {
	if(s > R || e < L || s > e) return 0.0;
	if(s >= L && e <= R) return ST[c];
	int mid = (s + e) >> 1;
	long double pp = queryST(c+c+1, s, mid, L, R);
	long double qq = queryST(c+c+2, mid + 1, e, L, R);
	return max(pp, qq);
}

int main()
{
   int n;
   scanf("%d", &n);
   for (int i = 0; i < n; i++) {
   	    long long x, y;
   	    scanf("%I64d %I64d", &x, &y);
   	    a[i].first = (long double)PI * x * x * y;
   	    a[i].second = -i;
   }
   sort(a, a + n);

   constructST(0, 0, n - 1);

   for (int i = 0; i < n; i++) {
   	    long double vol = a[i].first;
   	    int id = -a[i].second;
   	    long double Q = queryST(0, 0, n - 1, 0, id - 1);
   	    dp[id] = Q + vol;
   	    updateST(0, 0, n - 1, id, dp[id]);
   }
   long double ans = queryST(0, 0, n - 1, 0, n - 1);
   cout << setprecision(20) << ans << endl;
   return 0;
}


/*********************************ENTER THE DRAGON**********************************/

#include <cstdio>
#include <iostream>
#include <cmath>
#include <string>
#include <list>
#include <vector>
#include <algorithm>
#include <functional>
#include <utility>
#include <set>
#include <map>
#include <complex>
#include <queue>
#include <stack>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <string.h>
#include <cassert>
#include <climits>
#include <iomanip>
using namespace std;

/************************************************************************************/

const int maxn = 100100;
long double a[maxn], b[maxn];
long double PI = acos(-1.0);
long double ST[4 * maxn], dp[maxn];

void constructST(int c, int s, int e) {
	if (s==e)
	{
		ST[c] = 0.0;
		return;
	}
	int m = (s + e) >> 1;
	constructST(c+c+1, s, m);
	constructST(c+c+2, m+1, e);
	ST[c] = 0.0;
	return;
}

void updateST(int c, int s, int e, int x, long double val) {
	 if(s == e) {
	 	  ST[c] = val;
	 	  return;
	 }
	 int mid = (s + e) >> 1;
	 if(x <= mid)
	    updateST(c+c+1, s, mid, x, val);
	 else
	    updateST(c+c+2, mid + 1, e, x, val);
	 {
	 	 ST[c] = max(ST[c+c+1], ST[c+c+2]);
	 }
	 return;
}

long double queryST(int c, int s, int e, int L, int R) {
	if(s > R || e < L || s > e) return 0.0;
	if(s >= L && e <= R) return ST[c];
	int mid = (s + e) >> 1;
	long double pp = queryST(c+c+1, s, mid, L, R);
	long double qq = queryST(c+c+2, mid + 1, e, L, R);
	return max(pp, qq);
}

int main()
{
   int n;
   scanf("%d", &n);
   for (int i = 0; i < n; i++) {
   	    long long x, y;
   	    scanf("%I64d %I64d", &x, &y);
   	    a[i] = (long double)PI * x * x * y;
   	    b[i] = a[i];
   }
   sort(b, b + n);
   map<long double, int> ID;
   int cnt = 0;
   for (int i = 0; i < n; i++)
		if ((i == 0) || (b[i] > b[i - 1]))
			ID[b[i]] = cnt++;

   constructST(0, 0, n - 1);
   long double ans = 0.0;
   for (int i = 0; i < n; i++) {
   	    int id = ID[ a[i] ];
   	    long double Q = queryST(0, 0, n - 1, 0, id);
   	    dp[id] = Q + a[i];
   	    ans = max(ans, dp[id]);
   	    updateST(0, 0, n - 1, id, dp[id]);
   }

   cout << setprecision(20) << ans << endl;
   return 0;
}


/*********************************ENTER THE DRAGON**********************************/

#include <cstdio>
#include <iostream>
#include <cmath>
#include <string>
#include <list>
#include <vector>
#include <algorithm>
#include <functional>
#include <utility>
#include <set>
#include <map>
#include <complex>
#include <queue>
#include <stack>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <string.h>
#include <cassert>
#include <climits>
#include <iomanip>
using namespace std;

/************************************************************************************/

const int maxn = 100100;
pair<long double, int> a[maxn];
long double PI = 3.14159265359;
long double ST[4 * maxn], dp[maxn];

bool cmp(pair<long double, int> x, pair<long double, int> y) {
	 if (x.first != y.first)
	     return x.first < y.first;
	 return x.second > y.second;
}

void constructST(int c, int s, int e) {
	if (s==e)
	{
		ST[c] = 0.0;
		return;
	}
	int m = (s + e) >> 1;
	constructST(c+c+1, s, m);
	constructST(c+c+2, m+1, e);
	ST[c] = 0.0;
	return;
}

void updateST(int c, int s, int e, int x, long double val) {
	 if(s == e) {
	 	  ST[c] = val;
	 	  return;
	 }
	 int mid = (s + e) >> 1;
	 if(x <= mid)
	    updateST(c+c+1, s, mid, x, val);
	 else
	    updateST(c+c+2, mid + 1, e, x, val);
	 {
	 	 ST[c] = max(ST[c+c+1], ST[c+c+2]);
	 }
	 return;
}

long double queryST(int c, int s, int e, int L, int R) {
	if(s > R || e < L || s > e) return 0.0;
	if(s >= L && e <= R) return ST[c];
	int mid = (s + e) >> 1;
	long double pp = queryST(c+c+1, s, mid, L, R);
	long double qq = queryST(c+c+2, mid + 1, e, L, R);
	return max(pp, qq);
}

int main()
{
   int n;
   scanf("%d", &n);
   for (int i = 0; i < n; i++) {
   	    long long x, y;
   	    scanf("%I64d %I64d", &x, &y);
   	    a[i].first = (long double)PI * x * x * y;
   	    a[i].second = i;
   }
   sort(a, a + n, cmp);

   constructST(0, 0, n - 1);
   long double ans = 0.0;
   for (int i = 0; i < n; i++) {
   	    long double vol = a[i].first;
   	    int id = a[i].second;
   	    long double Q = queryST(0, 0, n - 1, 0, id - 1);
   	    dp[id] = Q + vol;
   	    ans = max(ans, dp[id]);
   	    updateST(0, 0, n - 1, id, dp[id]);
   }
   ans = max(ans, queryST(0, 0, n - 1, 0, n - 1));
   cout << setprecision(20) << ans << endl;
   return 0;
}


/*********************************ENTER THE DRAGON**********************************/

#include <cstdio>
#include <iostream>
#include <cmath>
#include <string>
#include <list>
#include <vector>
#include <algorithm>
#include <functional>
#include <utility>
#include <set>
#include <map>
#include <complex>
#include <queue>
#include <stack>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <string.h>
#include <cassert>
#include <climits>
#include <iomanip>
using namespace std;

/************************************************************************************/

const int maxn = 100100;
pair<long double, int> a[maxn];
long double PI = 3.14159265359;
long double ST[4 * maxn], dp[maxn];

void constructST(int c, int s, int e) {
	if (s==e)
	{
		ST[c] = 0.0;
		return;
	}
	int m = (s + e) >> 1;
	constructST(c+c+1, s, m);
	constructST(c+c+2, m+1, e);
	ST[c] = 0.0;
	return;
}

void updateST(int c, int s, int e, int x, long double val) {
	 if(s == e) {
	 	  ST[c] = val;
	 	  return;
	 }
	 int mid = (s + e) >> 1;
	 if(x <= mid)
	    updateST(c+c+1, s, mid, x, val);
	 else
	    updateST(c+c+2, mid + 1, e, x, val);
	 {
	 	 ST[c] = max(ST[c+c+1], ST[c+c+2]);
	 }
	 return;
}

long double queryST(int c, int s, int e, int L, int R) {
	if(s > R || e < L || s > e) return 0.0;
	if(s >= L && e <= R) return ST[c];
	int mid = (s + e) >> 1;
	long double pp = queryST(c+c+1, s, mid, L, R);
	long double qq = queryST(c+c+2, mid + 1, e, L, R);
	return max(pp, qq);
}

int main()
{
   int n;
   scanf("%d", &n);
   for (int i = 0; i < n; i++) {
   	    long long x, y;
   	    scanf("%I64d %I64d", &x, &y);
   	    a[i].first = (long double)PI * x * x * y;
   	    a[i].second = -i;
   }
   sort(a, a + n);

   constructST(0, 0, n - 1);

   for (int i = 0; i < n; i++) {
   	    long double vol = a[i].first;
   	    int id = -a[i].second;
   	    long double Q = queryST(0, 0, n - 1, 0, id);
   	    dp[id] = Q + vol;
   	    updateST(0, 0, n - 1, id, dp[id]);
   }
   long double ans = queryST(0, 0, n - 1, 0, n - 1);
   cout << setprecision(20) << ans << endl;
   return 0;
}


/*********************************ENTER THE DRAGON**********************************/

#include <cstdio>
#include <iostream>
#include <cmath>
#include <string>
#include <list>
#include <vector>
#include <algorithm>
#include <functional>
#include <utility>
#include <set>
#include <map>
#include <complex>
#include <queue>
#include <stack>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <string.h>
#include <cassert>
#include <climits>
#include <iomanip>
using namespace std;

/************************************************************************************/

const int maxn = 100100;
long long a[maxn], b[maxn];
long double PI = 3.14159265358979323846264338327950288419;
long long ST[4 * maxn], dp[maxn];

void constructST(int c, int s, int e) {
	if (s==e)
	{
		ST[c] = 0;
		return;
	}
	int m = (s + e) >> 1;
	constructST(c+c+1, s, m);
	constructST(c+c+2, m+1, e);
	ST[c] = 0;
	return;
}

void updateST(int c, int s, int e, int x, long long val) {
	 if(s == e) {
	 	  ST[c] = val;
	 	  return;
	 }
	 int mid = (s + e) >> 1;
	 if(x <= mid)
	    updateST(c+c+1, s, mid, x, val);
	 else
	    updateST(c+c+2, mid + 1, e, x, val);
	 {
	 	 ST[c] = max(ST[c+c+1], ST[c+c+2]);
	 }
	 return;
}

long long queryST(int c, int s, int e, int L, int R) {
	if(s > R || e < L || s > e) return 0;
	if(s >= L && e <= R) return ST[c];
	int mid = (s + e) >> 1;
	long long pp = queryST(c+c+1, s, mid, L, R);
	long long qq = queryST(c+c+2, mid + 1, e, L, R);
	return max(pp, qq);
}

int main()
{
   int n;
   scanf("%d", &n);
   for (int i = 0; i < n; i++) {
   	    long long x, y;
   	    scanf("%I64d %I64d", &x, &y);
   	    a[i] = x * x * y;
   	    b[i] = a[i];
   }
   sort(b, b + n);
   map<long long, int> ID;
   int cnt = 0;
   for (int i = 0; i < n; i++)
		if ((i == 0) || (b[i] > b[i - 1]))
			ID[b[i]] = cnt++;

   constructST(0, 0, n - 1);

   long long ans = 0;
   for (int i = 0; i < n; i++) {
   	    int id = ID[ a[i] ];
   	    dp[id] = a[i];
   	    if (id > 0) dp[id] += queryST(0, 0, n - 1, 0, id - 1);
   	    ans = max(ans, dp[id]);
   	    updateST(0, 0, n - 1, id, dp[id]);
   }

   cout << setprecision(20) << (PI * ans) << endl;
   return 0;
}


/*********************************ENTER THE DRAGON**********************************/

#include <cstdio>
#include <iostream>
#include <cmath>
#include <string>
#include <list>
#include <vector>
#include <algorithm>
#include <functional>
#include <utility>
#include <set>
#include <map>
#include <complex>
#include <queue>
#include <stack>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <string.h>
#include <cassert>
#include <climits>
#include <iomanip>
using namespace std;

/************************************************************************************/

const int maxn = 100100;
pair<long double, int> a[maxn];
long double PI = 3.14159265359;
long double ST[4 * maxn], dp[maxn];

void constructST(int c, int s, int e) {
	if (s==e)
	{
		ST[c] = 0.0;
		return;
	}
	int m = (s + e) >> 1;
	constructST(c+c+1, s, m);
	constructST(c+c+2, m+1, e);
	ST[c] = 0.0;
	return;
}

void updateST(int c, int s, int e, int x, long double val) {
	 if(s == e) {
	 	  ST[c] = val;
	 	  return;
	 }
	 int mid = (s + e) >> 1;
	 if(x <= mid)
	    updateST(c+c+1, s, mid, x, val);
	 else
	    updateST(c+c+2, mid + 1, e, x, val);
	 {
	 	 ST[c] = max(ST[c+c+1], ST[c+c+2]);
	 }
	 return;
}

long double queryST(int c, int s, int e, int L, int R) {
	if(s > R || e < L || s > e) return 0.0;
	if(s >= L && e <= R) return ST[c];
	int mid = (s + e) >> 1;
	long double pp = queryST(c+c+1, s, mid, L, R);
	long double qq = queryST(c+c+2, mid + 1, e, L, R);
	return max(pp, qq);
}

int main()
{
   int n;
   scanf("%d", &n);
   for (int i = 0; i < n; i++) {
   	    long long x, y;
   	    scanf("%I64d %I64d", &x, &y);
   	    a[i].first = (long double)PI * x * x * y;
   	    a[i].second = i;
   }
   sort(a, a + n);
   int cur = 0;
   for (int i = 1; i < n; i++) {
   	    cur+= (a[i].first != a[i - 1].first);
   	    a[i].second = cur;
   }

   constructST(0, 0, n - 1);
   long double ans = 0.0;
   for (int i = 0; i < n; i++) {
   	    long double vol = a[i].first;
   	    int id = a[i].second;
   	    long double Q = queryST(0, 0, n - 1, 0, id - 1);
   	    dp[id] = Q + vol;
   	    updateST(0, 0, n - 1, id, dp[id]);
   }
   ans = queryST(0, 0, n - 1, 0, cur);
   cout << setprecision(20) << ans << endl;
   return 0;
}


/*********************************ENTER THE DRAGON**********************************/

#include <cstdio>
#include <iostream>
#include <cmath>
#include <string>
#include <list>
#include <vector>
#include <algorithm>
#include <functional>
#include <utility>
#include <set>
#include <map>
#include <complex>
#include <queue>
#include <stack>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <string.h>
#include <cassert>
#include <climits>
#include <iomanip>
using namespace std;

/************************************************************************************/

const int maxn = 100100;
pair<long double, int> a[maxn];
long double PI = 3.14159265359;
long double ST[4 * maxn], dp[maxn];

void constructST(int c, int s, int e) {
	if (s==e)
	{
		ST[c] = 0.0;
		return;
	}
	int m = (s + e) >> 1;
	constructST(c+c+1, s, m);
	constructST(c+c+2, m+1, e);
	ST[c] = 0.0;
	return;
}

void updateST(int c, int s, int e, int x, long double val) {
	 if(s == e) {
	 	  ST[c] = val;
	 	  return;
	 }
	 int mid = (s + e) >> 1;
	 if(x <= mid)
	    updateST(c+c+1, s, mid, x, val);
	 else
	    updateST(c+c+2, mid + 1, e, x, val);
	 {
	 	 ST[c] = max(ST[c+c+1], ST[c+c+2]);
	 }
	 return;
}

long double queryST(int c, int s, int e, int L, int R) {
	if(s > R || e < L || s > e) return 0.0;
	if(s >= L && e <= R) return ST[c];
	int mid = (s + e) >> 1;
	long double pp = queryST(c+c+1, s, mid, L, R);
	long double qq = queryST(c+c+2, mid + 1, e, L, R);
	return max(pp, qq);
}

int main()
{
   int n;
   scanf("%d", &n);
   for (int i = 0; i < n; i++) {
   	    long long x, y;
   	    scanf("%I64d %I64d", &x, &y);
   	    a[i].first = (long double)PI * x * x * y;
   	    a[i].second = i;
   }
   sort(a, a + n);
   int cur = 0;
   for (int i = 1; i < n; i++) {
   	    cur+= (a[i].second != a[i - 1].second);
   	    a[i].second = cur;
   }

   constructST(0, 0, n - 1);
   long double ans = 0.0;
   for (int i = 0; i < n; i++) {
   	    long double vol = a[i].first;
   	    int id = a[i].second;
   	    long double Q = queryST(0, 0, n - 1, 0, id - 1);
   	    dp[id] = Q + vol;
   	    ans = max(ans, dp[id]);
   	    updateST(0, 0, n - 1, id, dp[id]);
   }
   cout << setprecision(20) << ans << endl;
   return 0;
}


/*********************************ENTER THE DRAGON**********************************/

#include <cstdio>
#include <iostream>
#include <cmath>
#include <string>
#include <list>
#include <vector>
#include <algorithm>
#include <functional>
#include <utility>
#include <set>
#include <map>
#include <complex>
#include <queue>
#include <stack>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <string.h>
#include <cassert>
#include <climits>
#include <iomanip>
using namespace std;

/************************************************************************************/

const int maxn = 100100;
pair<long double, int> a[maxn];
long double PI = 3.141592653589793238462643383279;
long double ST[4 * maxn], dp[maxn];

bool cmp(pair<long double, int> x, pair<long double, int> y) {
	 if (x.first != y.first)
	     return x.first < y.first;
	 return x.second > y.second;
}

void constructST(int c, int s, int e) {
	if (s==e)
	{
		ST[c] = 0.0;
		return;
	}
	int m = (s + e) >> 1;
	constructST(c+c+1, s, m);
	constructST(c+c+2, m+1, e);
	ST[c] = 0.0;
	return;
}

void updateST(int c, int s, int e, int x, long double val) {
	 if(s == e) {
	 	  ST[c] = val;
	 	  return;
	 }
	 int mid = (s + e) >> 1;
	 if(x <= mid)
	    updateST(c+c+1, s, mid, x, val);
	 else
	    updateST(c+c+2, mid + 1, e, x, val);
	 {
	 	 ST[c] = max(ST[c+c+1], ST[c+c+2]);
	 }
	 return;
}

long double queryST(int c, int s, int e, int L, int R) {
	if(s > R || e < L || s > e) return 0.0;
	if(s >= L && e <= R) return ST[c];
	int mid = (s + e) >> 1;
	long double pp = queryST(c+c+1, s, mid, L, R);
	long double qq = queryST(c+c+2, mid + 1, e, L, R);
	return max(pp, qq);
}

int main()
{
   int n;
   scanf("%d", &n);
   for (int i = 0; i < n; i++) {
   	    long long x, y;
   	    scanf("%I64d %I64d", &x, &y);
   	    a[i].first = (long double)PI * x * x * y;
   	    a[i].second = i;
   }
   sort(a, a + n, cmp);

   constructST(0, 0, n - 1);
   long double ans = 0.0;
   for (int i = 0; i < n; i++) {
   	    long double vol = a[i].first;
   	    int id = a[i].second;
   	    long double Q = queryST(0, 0, n - 1, 0, id - 1);
   	    dp[id] = Q + vol;
   	    ans = max(ans, dp[id]);
   	    updateST(0, 0, n - 1, id, dp[id]);
   }
   //ans = max(ans, queryST(0, 0, n - 1, 0, n - 2));
   cout << setprecision(20) << ans << endl;
   return 0;
}


/*********************************ENTER THE DRAGON**********************************/

#include <cstdio>
#include <iostream>
#include <cmath>
#include <string>
#include <list>
#include <vector>
#include <algorithm>
#include <functional>
#include <utility>
#include <set>
#include <map>
#include <complex>
#include <queue>
#include <stack>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <string.h>
#include <cassert>
#include <climits>
#include <iomanip>
using namespace std;

/************************************************************************************/

const int maxn = 100100;
pair<long double, int> a[maxn];
long double PI = 3.141592653589793238462643383279;
long double ST[4 * maxn], dp[maxn];

bool cmp(pair<long double, int> x, pair<long double, int> y) {
	 if (x.first != y.first)
	     return x.first < y.first;
	 return x.second > y.second;
}

void constructST(int c, int s, int e) {
	if (s==e)
	{
		ST[c] = 0.0;
		return;
	}
	int m = (s + e) >> 1;
	constructST(c+c+1, s, m);
	constructST(c+c+2, m+1, e);
	ST[c] = 0.0;
	return;
}

void updateST(int c, int s, int e, int x, long double val) {
	 if(s == e) {
	 	  ST[c] = val;
	 	  return;
	 }
	 int mid = (s + e) >> 1;
	 if(x <= mid)
	    updateST(c+c+1, s, mid, x, val);
	 else
	    updateST(c+c+2, mid + 1, e, x, val);
	 {
	 	 ST[c] = max(ST[c+c+1], ST[c+c+2]);
	 }
	 return;
}

long double queryST(int c, int s, int e, int L, int R) {
	if(s > R || e < L || s > e) return 0.0;
	if(s >= L && e <= R) return ST[c];
	int mid = (s + e) >> 1;
	long double pp = queryST(c+c+1, s, mid, L, R);
	long double qq = queryST(c+c+2, mid + 1, e, L, R);
	return max(pp, qq);
}

int main()
{
   int n;
   scanf("%d", &n);
   for (int i = 0; i < n; i++) {
   	    long long x, y;
   	    scanf("%I64d %I64d", &x, &y);
   	    a[i].first = (long double)PI * x * x * y;
   	    a[i].second = i;
   }
   sort(a, a + n, cmp);

   constructST(0, 0, n - 1);
   long double ans = 0.0;
   for (int i = 0; i < n; i++) {
   	    long double vol = a[i].first;
   	    int id = a[i].second;
   	    long double Q = queryST(0, 0, n - 1, 0, id - 1);
   	    dp[id] = Q + vol;
   	    updateST(0, 0, n - 1, id, dp[id]);
   }
   ans = queryST(0, 0, n - 1, 0, n - 2);
   cout << setprecision(20) << ans << endl;
   return 0;
}


/*********************************ENTER THE DRAGON**********************************/

#include <cstdio>
#include <iostream>
#include <cmath>
#include <string>
#include <list>
#include <vector>
#include <algorithm>
#include <functional>
#include <utility>
#include <set>
#include <map>
#include <complex>
#include <queue>
#include <stack>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <string.h>
#include <cassert>
#include <climits>
#include <iomanip>
using namespace std;

/************************************************************************************/

const int maxn = 100100;
pair<long double, int> a[maxn];
long double PI = 3.14159265359;
long double ST[4 * maxn], dp[maxn];
map<long double, int> maxId;

void constructST(int c, int s, int e) {
	if (s==e)
	{
		ST[c] = 0.0;
		return;
	}
	int m = (s + e) >> 1;
	constructST(c+c+1, s, m);
	constructST(c+c+2, m+1, e);
	ST[c] = 0.0;
	return;
}

void updateST(int c, int s, int e, int x, long double val) {
	 if(s == e) {
	 	  ST[c] = val;
	 	  return;
	 }
	 int mid = (s + e) >> 1;
	 if(x <= mid)
	    updateST(c+c+1, s, mid, x, val);
	 else
	    updateST(c+c+2, mid + 1, e, x, val);
	 {
	 	 ST[c] = max(ST[c+c+1], ST[c+c+2]);
	 }
	 return;
}

long double queryST(int c, int s, int e, int L, int R) {
	if(s > R || e < L || s > e) return 0.0;
	if(s >= L && e <= R) return ST[c];
	int mid = (s + e) >> 1;
	long double pp = queryST(c+c+1, s, mid, L, R);
	long double qq = queryST(c+c+2, mid + 1, e, L, R);
	return max(pp, qq);
}

int main()
{
   int n;
   scanf("%d", &n);
   for (int i = 0; i < n; i++) {
   	    long long x, y;
   	    scanf("%I64d %I64d", &x, &y);
   	    a[i].first = (long double)PI * x * x * y;
   	    a[i].second = i;
   }
   sort(a, a + n);
   for (int i = 0; i < n; i++) {
   	    maxId[ a[i].first ] = max(maxId[ a[i].first ], a[i].second);
   }

   constructST(0, 0, n - 1);
   long double ans = 0.0;
   for (int i = 0; i < n; i++) {
   	    if (i > 0 && a[i].first == a[i - 1].first) continue;
   	    long double vol = a[i].first;
   	    int id = maxId[ vol ];
   	    long double Q = queryST(0, 0, n - 1, 0, id - 1);
   	    dp[id] = Q + vol;
   	    ans = max(ans, dp[id]);
   	    updateST(0, 0, n - 1, id, dp[id]);
   }
   cout << setprecision(20) << ans << endl;
   return 0;
}


/*********************************ENTER THE DRAGON**********************************/

#include <cstdio>
#include <iostream>
#include <cmath>
#include <string>
#include <list>
#include <vector>
#include <algorithm>
#include <functional>
#include <utility>
#include <set>
#include <map>
#include <complex>
#include <queue>
#include <stack>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <string.h>
#include <cassert>
#include <climits>
#include <iomanip>
using namespace std;

/************************************************************************************/

const int maxn = 100100;
pair<long double, int> a[maxn];
long double PI = 3.14159265359;
long double ST[4 * maxn], dp[maxn];
map<long double, int> maxId;

void constructST(int c, int s, int e) {
	if (s==e)
	{
		ST[c] = 0.0;
		return;
	}
	int m = (s + e) >> 1;
	constructST(c+c+1, s, m);
	constructST(c+c+2, m+1, e);
	ST[c] = 0.0;
	return;
}

void updateST(int c, int s, int e, int x, long double val) {
	 if(s == e) {
	 	  ST[c] = val;
	 	  return;
	 }
	 int mid = (s + e) >> 1;
	 if(x <= mid)
	    updateST(c+c+1, s, mid, x, val);
	 else
	    updateST(c+c+2, mid + 1, e, x, val);
	 {
	 	 ST[c] = max(ST[c+c+1], ST[c+c+2]);
	 }
	 return;
}

long double queryST(int c, int s, int e, int L, int R) {
	if(s > R || e < L || s > e) return 0.0;
	if(s >= L && e <= R) return ST[c];
	int mid = (s + e) >> 1;
	long double pp = queryST(c+c+1, s, mid, L, R);
	long double qq = queryST(c+c+2, mid + 1, e, L, R);
	return max(pp, qq);
}

int main()
{
   int n;
   scanf("%d", &n);
   for (int i = 0; i < n; i++) {
   	    long long x, y;
   	    scanf("%I64d %I64d", &x, &y);
   	    a[i].first = (long double)PI * x * x * y;
   	    a[i].second = i;
   }
   sort(a, a + n);
   for (int i = 0; i < n; i++) {
   	    maxId[ a[i].first ] = max(maxId[ a[i].first ], a[i].second);
   }

   constructST(0, 0, n - 1);
   long double ans = 0.0;
   for (int i = 0; i < n; i++) {
   	    if (i > 0 && a[i].first == a[i - 1].first) continue;
   	    long double vol = a[i].first;
   	    int id = maxId[ vol ];
   	    long double Q = queryST(0, 0, n - 1, 0, id - 1);
   	    dp[id] = Q + vol;
   	    ans = max(ans, dp[id]);
   	    updateST(0, 0, n - 1, id, dp[id]);
   }
   printf("%.20Lf\n", ans);
   return 0;
}


/*********************************ENTER THE DRAGON**********************************/

#include <cstdio>
#include <iostream>
#include <cmath>
#include <string>
#include <list>
#include <vector>
#include <algorithm>
#include <functional>
#include <utility>
#include <set>
#include <map>
#include <complex>
#include <queue>
#include <stack>
#include <cstdlib>
#include <ctime>
#include <cstring>
#include <string.h>
#include <cassert>
#include <climits>
#include <iomanip>
using namespace std;

/************************************************************************************/

const int maxn = 100100;
pair<long double, int> a[maxn];
long double PI = 3.141592653589793238462643383279;
long double ST[4 * maxn], dp[maxn];

bool cmp(pair<long double, int> x, pair<long double, int> y) {
	 if (x.first != y.first)
	     return x.first < y.first;
	 return x.second > y.second;
}

void constructST(int c, int s, int e) {
	if (s==e)
	{
		ST[c] = 0.0;
		return;
	}
	int m = (s + e) >> 1;
	constructST(c+c+1, s, m);
	constructST(c+c+2, m+1, e);
	ST[c] = 0.0;
	return;
}

void updateST(int c, int s, int e, int x, long double val) {
	 if(s == e) {
	 	  ST[c] = val;
	 	  return;
	 }
	 int mid = (s + e) >> 1;
	 if(x <= mid)
	    updateST(c+c+1, s, mid, x, val);
	 else
	    updateST(c+c+2, mid + 1, e, x, val);
	 {
	 	 ST[c] = max(ST[c+c+1], ST[c+c+2]);
	 }
	 return;
}

long double queryST(int c, int s, int e, int L, int R) {
	if(s > R || e < L || s > e) return 0.0;
	if(s >= L && e <= R) return ST[c];
	int mid = (s + e) >> 1;
	long double pp = queryST(c+c+1, s, mid, L, R);
	long double qq = queryST(c+c+2, mid + 1, e, L, R);
	return max(pp, qq);
}

int main()
{
   int n;
   scanf("%d", &n);
   for (int i = 0; i < n; i++) {
   	    long long x, y;
   	    scanf("%I64d %I64d", &x, &y);
   	    a[i].first = (long double)PI * x * x * y;
   	    a[i].second = i;
   }
   sort(a, a + n, cmp);

   constructST(0, 0, n - 1);
   long double ans = 0.0;
   for (int i = 0; i < n; i++) {
   	    long double vol = a[i].first;
   	    int id = a[i].second;
   	    long double Q = queryST(0, 0, n - 1, 0, id - 1);
   	    dp[id] = Q + vol;
   	    updateST(0, 0, n - 1, id, dp[id]);
   }
   ans = queryST(0, 0, n - 1, 0, n - 1);
   cout << setprecision(20) << ans << endl;
   return 0;
}


#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]);
		b[i] = a[i-1]>(a[x]+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 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(12) << 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 f(long long int , long long int* , long long int* , long long int* );
long long int f1(long long int , long long int* , long long int* , long long int* );
int main()
{
	long long int n, i;
	cin >> n;
	long long int r[n+1], h[n+1], a[n+1], v[n+1], b[n+1];
	for(i=1; i<=n; i++)
	{
		cin >> r[i] >> h[i];
		a[i] = 0;
		b[i] =0;
	}
	for(i=1; i<=n; i++)
		v[i] = r[i]*r[i]*h[i];
	a[0] = 0;
	b[0] = 0;
	v[0] = 0;
	cout << setprecision(15)<<3.14159265358979*((double)f(n, a, v, b));
	return 0;
}
long long int f1(long long int n, long long int* b, long long int* v, long long int* a)
{
	long long i;
	if(n == 0)
		return 0;
	if(n == 1)
	{
		b[n] = v[n];
		return b[n];
	}
	if(b[n]!=0)
		return b[n];
	i = n-1;
	while(f1(i, b, v, a) >= v[n])
		i--;
	if(f(n-1, a, v, b) > f(i, a, v, b)+v[n])
	{
		b[n] = b[n-1];
	}
	else
	{
		b[n] = v[n];
	}
	return b[n];
}
long long int f(long long int n, long long int* a, long long int* v, long long int* b)
{
	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(f1(i, b, v, a) >= v[n])
		i--;
	a[n] = mxi(f(n-1, a, v,b), f(i, a, v, b)+v[n]);
	return a[n];
}