codeforces 629D 树状数组+LIS
题意:n个圆柱形蛋糕,给你半径 r 和高度 h,一个蛋糕只能放在一个体积比它小而且序号小于它的蛋糕上面,问你这样形成的上升序列中,体积和最大是多少
分析:根据他们的体积进行离散化,然后建树状数组,按照序号进行循环,每次查询体积比它小的蛋糕形成的最大体积
注:因为是按照序号进行循环,所以序号一定是严格小于它的,时间复杂度O(nlogn)
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
#include <iostream> #include <cstdio> #include <algorithm> using namespace std; typedef long long LL; const int N=1e5+5; const double pi=3.14159265358; LL c[N],a[N],h,r,o[N]; int cnt; void update(int i,LL t) { for(;i<=cnt;i+=(i&(-i))) c[i]=max(c[i],t); } LL query(int i) { LL ans=0; for(;i>0;i-=(i&(-i))) ans=max(ans,c[i]); return ans; } int main() { int n; scanf("%d",&n); for(int i=1;i<=n;++i) { scanf("%I64d%I64d",&r,&h); a[i]=o[i]=r*r*h; } sort(a+1,a+1+n); cnt=1; for(int i=2;i<=n;++i) if(a[i]!=a[i-1])a[++cnt]=a[i]; LL res=0; for(int i=1;i<=n;++i) { int pos=lower_bound(a+1,a+1+cnt,o[i])-a; LL tmp=query(pos-1)+o[i]; res=max(tmp,res); update(pos,tmp); } printf("%.10f\n",(double)(res)*pi); return 0; }