codeforces 629D 树状数组+LIS

时间:2021-05-13 19:27:46

题意:n个圆柱形蛋糕,给你半径 r 和高度 h,一个蛋糕只能放在一个体积比它小而且序号小于它的蛋糕上面,问你这样形成的上升序列中,体积和最大是多少

分析:根据他们的体积进行离散化,然后建树状数组,按照序号进行循环,每次查询体积比它小的蛋糕形成的最大体积

注:因为是按照序号进行循环,所以序号一定是严格小于它的,时间复杂度O(nlogn)

codeforces 629D 树状数组+LIScodeforces 629D 树状数组+LIS
#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;
}
View Code