Codeforces 629D.( Babaei and Birthday Cake)

D. Babaei and Birthday Cake
 

As you know, every birthday party has a cake! This time, Babaei is going to prepare the very special birthday party's cake.

Simple cake is a cylinder of some radius and height. The volume of the simple cake is equal to the volume of corresponding cylinder. Babaei has n simple cakes and he is going to make a special cake placing some cylinders on each other.

However, there are some additional culinary restrictions. The cakes are numbered in such a way that the cake number i can be placed only on the table or on some cake number j where j < i. Moreover, in order to impress friends Babaei will put the cake i on top of the cake j only if the volume of the cake i is strictly greater than the volume of the cake j.

Babaei wants to prepare a birthday cake that has a maximum possible total volume. Help him find this value.

Input

The first line of the input contains a single integer n (1 ≤ n ≤ 100 000) — the number of simple cakes Babaei has.

Each of the following n lines contains two integers ri and hi (1 ≤ ri, hi ≤ 10 000), giving the radius and height of the i-th cake.

Output

Print the maximum volume of the cake that Babaei can make. Your answer will be considered correct if its absolute or relative error does not exceed 10 - 6.

Namely: let's assume that your answer is a, and the answer of the jury is b. The checker program will consider your answer correct, if .

Examples
input
2
100 30
40 10
output
942477.796077000
input
4
1 1
9 7
1 4
10 7
output
3983.539484752
Note

In first sample, the optimal way is to choose the cake number 1.

In second sample, the way to get the maximum volume is to use cakes with indices 1, 2 and 4.

题意:做蛋糕,给出N个半径,和高的圆柱,要求后面的体积比前面大的可以堆在前一个的上面,求最大的体积和。

思路:dp,以当前的体积为当前最上层的最大值,dp[i]=max(dp[j])+tiji[i](j<i&&tiji[i]>tiji[j]);

由于这样时间复杂度为N*N,所以想到离散化体积,然后用线段树去维护区间最大值,lisan[i]为离散化后体积对应的值,那么要查[1,lisan[i]-1];这保证了体积比当前值小,

线段树保存在区间以某个点为最上的最大值,由于按顺序来,所以顺序要求以保证。复杂度N*(logN)2;

  1 #include<stdio.h>
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<string.h>
  5 #include<queue>
  6 #include<stack>
  7 #include<math.h>
  8 #include<iomanip>
  9 using namespace std;void update(int k);
 10 int cmp(const void*p,const void*q);
 11 long long  query(int l,int r,int n,int m,int id);
 12 void build(int l,int r,int id);
 13 const double pi=acos(-1);
 14 long long tree[5*100005];
 15 struct node
 16 {
 17     int id;
 18     long long tiji;
 19 };
 20 node dian[100005];
 21 long long  dui[100005];
 22 int lisan[100005];
 23 int dibu[100005];
 24 int main(void)
 25 {
 26     int i,j,k;long long p,q;
 27     //freopen("data.in","r",stdin);
 28     //freopen("wrong.out","w",stdout);
 29     while(scanf("%d",&k)!=EOF)
 30     {   memset(tree,0,sizeof(tree));
 31         long long  maxx=0;
 32         for(i=1;i<=k;i++)
 33         {
 34             scanf("%I64d %I64d",&p,&q);
 35            dian[i].tiji=p*p*q;
 36            dian[i].id=i;
 37         }
 38         qsort(dian+1,k,sizeof(node),cmp);
 39         int ans=1;lisan[dian[1].id]=ans;dui[dian[1].id]=dian[1].tiji;
 40         for(i=2;i<=k;i++)
 41         {
 42             if(dian[i].tiji!=dian[i-1].tiji)
 43                 ans++;
 44             lisan[dian[i].id]=ans;
 45             dui[dian[i].id]=dian[i].tiji;
 46         }build(1,ans,0);
 47         for(i=1;i<=k;i++)
 48         {
 49             long long  tt=query(1,lisan[i]-1,1,ans,0);
 50            long long  mn=tt+dui[i];
 51             if(mn>maxx)
 52             {
 53                 maxx=mn;
 54             }
 55             if(mn>tree[dibu[lisan[i]]])
 56             {   tree[dibu[lisan[i]]]=mn;
 57                 update(dibu[lisan[i]]);
 58             }
 59         }long double MN=1.0*maxx*pi;
 60        cout<<setprecision(9)<<MN<<endl;
 61     }return 0;
 62 }
 63 int cmp(const void*p,const void*q)
 64 {
 65     node*nn=(node*)p;
 66     node*mm=(node*)q;
 67     return nn->tiji>mm->tiji?1:-1;
 68 }
 69 void build(int l,int r,int id)
 70 {
 71     if(l==r)
 72     {
 73         dibu[l]=id;
 74     }
 75     else
 76     {
 77         build(l,(l+r)/2,2*id+1);
 78         build((l+r)/2+1,r,2*id+2);
 79     }
 80 }
 81 long long query(int l,int r,int n,int m,int id)
 82 {   if(r==0)return 0;
 83     if(l>m||r<n)
 84     {
 85         return 0;
 86     }
 87     else if(l<=n&&r>=m)
 88     {
 89         return tree[id];
 90     }
 91     else
 92     {   long long  x;long long  y;
 93         x=query(l,r,n,(n+m)/2,2*id+1);
 94         y=query(l,r,(n+m)/2+1,m,2*id+2);
 95         return max(x,y);
 96     }
 97 }
 98 void update(int k)
 99 {
100     int ss=(k-1)/2;
101     while(ss>=0)
102     {
103         tree[ss]=max(tree[2*ss+1],tree[2*ss+2]);
104         if(ss==0)
105                break;
106         ss=(ss-1)/2;
107     }
108 }
  1 #include<stdio.h>
  2 #include<algorithm>
  3 #include<iostream>
  4 #include<string.h>
  5 #include<queue>
  6 #include<stack>
  7 #include<math.h>
  8 #include<iomanip>
  9 using namespace std;
 10 int cmp(const void*p,const void*q);
 11 long long  query(int l,int r,int n,int m,int id);
 12 void  update(int l,int r,int nn,int mm,int k,long long cc);
 13 const double pi=acos(-1);
 14 long long tree[5*100005];
 15 struct node
 16 {
 17     int id;
 18     long long tiji;
 19 };
 20 node dian[100005];
 21 long long  dui[100005];
 22 int lisan[100005];
 23 int main(void)
 24 {
 25     int i,j,k;long long p,q;
 26     //freopen("data.in","r",stdin);
 27     //freopen("wrong.out","w",stdout);
 28     while(scanf("%d",&k)!=EOF)
 29     {   memset(tree,0,sizeof(tree));
 30         long long  maxx=0;
 31         for(i=1;i<=k;i++)
 32         {
 33             scanf("%I64d %I64d",&p,&q);
 34            dian[i].tiji=p*p*q;
 35            dui[i]=p*p*q;
 36            dian[i].id=i;
 37         }
 38         qsort(dian+1,k,sizeof(node),cmp);
 39         int ans=1;lisan[dian[1].id]=ans;dui[dian[1].id]=dian[1].tiji;
 40         for(i=2;i<=k;i++)
 41         {
 42             if(dian[i].tiji!=dian[i-1].tiji)
 43                 ans++;
 44             lisan[dian[i].id]=ans;
 45         }long long tt;
 46         for(i=1;i<=k;i++)
 47         { if(lisan[i]!=1)
 48            tt=query(1,lisan[i]-1,1,ans,0);
 49            else tt=0;
 50            long long  mn=tt+dui[i];
 51             if(mn>maxx)
 52             {
 53                 maxx=mn;
 54             }
 55         update(lisan[i],lisan[i],1,ans,0,mn);
 56         }
 57         double MN=1.0*maxx*pi;
 58       printf("%.9f
",MN);
 59     }return 0;
 60 }
 61 int cmp(const void*p,const void*q)
 62 {
 63     node*nn=(node*)p;
 64     node*mm=(node*)q;
 65     return nn->tiji>mm->tiji?1:-1;
 66 }
 67 long long query(int l,int r,int n,int m,int id)
 68 {
 69     if(l>m||r<n)
 70     {
 71         return 0;
 72     }
 73     else if(l<=n&&r>=m)
 74     {
 75         return tree[id];
 76     }
 77     else
 78     {   long long  x;long long  y;
 79         x=query(l,r,n,(n+m)/2,2*id+1);
 80         y=query(l,r,(n+m)/2+1,m,2*id+2);
 81         return max(x,y);
 82     }
 83 }
 84 
 85 void update(int l,int r,int nn,int mm,int k,long long cc)
 86 {
 87 
 88     if(l>mm||r<nn)
 89     {
 90         return ;
 91     }
 92     else if(l==nn&&r==mm)
 93     {
 94             tree[k]=max(cc,tree[k]);
 95         return ;
 96     }
 97     else
 98     {
 99         update(l,r,nn,(nn+mm)/2,2*k+1,cc);
100         update(l,r,(nn+mm)/2+1,mm,2*k+2,cc);
101         tree[k]=max(tree[2*k+1],tree[2*k+2]);
102     }
103 }
不同的单点更新
油!油!you@
原文地址:https://www.cnblogs.com/zzuli2sjy/p/5208035.html