cf 629D Babaei and Birthday Cake
普及组dp*2
有\(n\)个蛋糕,每个蛋糕有一定体积(是圆柱体)。能把一个\(j\)蛋糕放在另一个\(i\)上面的充要条件是\(i<j\)并且\(V_i<V_j\)。问能落成的新蛋糕的最大体积。
\(dp[i]\)表示到达\(i\),且\(i\)被选,最大的体积。
\[dp[i]=max_{1\le j < i,V_j<V_i}(dp[j]+V_i)
\]
离散化以后线段树或者树状数组转移都行
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
template<typename T> inline T readin(T &rt) {
char c; T tmp=0,x=1; c=getchar();
while(c>'9' || c<'0') {if(c=='-') x=-1; c=getchar();}
while(c>='0' && c<='9') {tmp=tmp*10+c-'0'; c=getchar();}
return rt=tmp*x;
}
const int maxN=100000+10;
const double Pi=acos(-1.0);
int n,r[maxN],h[maxN];
ll V[maxN];
ll dp[maxN];
map<ll ,int > rfl;
typedef pair<ll ,int > pli;
#define fir first
#define sec second
#define MP make_pair
pli ck[maxN];
ll bmax[maxN];
inline int lowbit(int x) {return x&(-x);}
ll getmax(int pos) {
ll ret=0;
while(pos>0) {
ret=max(ret,bmax[pos]);
pos-=lowbit(pos);
}
return ret;
}
void upd(int pos,ll val) {
while(pos<=n) {
bmax[pos]=max(bmax[pos],val);
pos+=lowbit(pos);
}
}
int main() {
readin(n);
for(int i=1;i<=n;i++) readin(r[i]),readin(h[i]);
for(int i=1;i<=n;i++) {
V[i]=1ll*r[i]*r[i]*h[i];
ck[i]=MP(V[i],i);
}
sort(ck+1,ck+1+n);
int sz=unique(ck+1,ck+1+n)-(ck+1);
for(int i=1;i<=sz;i++) rfl[ck[i].fir]=i;
ll ans=0.0;
for(int i=1;i<=n;i++) {
dp[i]=getmax(rfl[V[i]]-1)+V[i];
ans=max(ans,dp[i]);
upd(rfl[V[i]],dp[i]);
}
printf("%.7lf\n",1.0*ans*Pi);
return 0;
}