这个题有点像lis,但是又不是常规的lis,因为它不是要求子序列最长,而是要求子序列的权值最大,所以用树状数组来维护这个最大值,tree[i]表示当第i个simple cake在最上层时,cake的体积最大是多少。那么本题的做法就是先算出每个simple cake的体积,然后给它们排序,然后遍历原始顺序的simple cake,设为i,找到i在排好序的数组中的位置pos,找到[1,pos-1]区间内树的最大值,把i插进去,更新树状数组。
#include <cstdio>
#include <cstdlib>
#include <stack>
#include <map>
#include <cmath>
#include <iostream>
#include <algorithm>
#define LL long long
using namespace std;
const double pi = acos(-1.0);
LL v1[100005], v2[100005], tree[1000005];
int n;
int lowbit(int x)
{
return x&-x;
}
LL query(int pos)
{
LL ans = 0;
while(pos > 0)
{
ans = max(ans, tree[pos]);
pos -= lowbit(pos);
}
return ans;
}
void update(int pos, LL key)
{
while(pos <= n)
{
tree[pos] = max(tree[pos], key);
pos += lowbit(pos);
}
}
int main()
{
//freopen("ztest.txt","r",stdin);
scanf("%d", &n);
LL r, h;
for(int i = 1; i <= n; i++)
{
scanf("%lld%lld",&r, &h);
v1[i] = v2[i] = r*r*h;
}
sort(v1+1, v1+n+1);
int tot = unique(v1+1, v1+n+1)-v1;
LL ans = 0;
for(int i = 1; i <= n; i++)
{
int pos = lower_bound(v1+1, v1+tot+1, v2[i])-v1;
LL temp = query(pos-1)+v2[i];
ans = max(ans, temp);
update(pos, temp);
}
printf("%.9lf\n",(double)ans*pi);
return 0;
}