Descriptionnode
As you know, every birthday party has a cake! This time, Babaei is going to prepare the very special birthday party's cake.ios
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.ide
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.ui
Babaei wants to prepare a birthday cake that has a maximum possible total volume. Help him find this value.this
Inputspa
The first line of the input contains a single integer n (1 ≤ n ≤ 100 000) — the number of simple cakes Babaei has.3d
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.rest
Outputcode
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.orm
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 .
Sample Input
2 100 30 40 10
942477.796077000
4 1 1 9 7 1 4 10 7
3983.539484752
Hint
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.
題意:找到累計最多的蛋糕體積。兩個蛋糕累計條件(j < i && v[j] < v[i])。
思路:能夠用最長上升子序列的 dp 來作,體積爲數列元素。 可是數據太大,查詢 j = 1 到 j < i 時須要浪費 O(n)的時間。時間複雜度就是 O(n^2) 確定會TEL。所以查詢以及更新利用線段樹來維護。將區間的從小到大抽象成體積 v[i] 從小到大,每次利用線段樹查詢和更新 dp[i]便可。時間複雜度爲 O(n*logn)。
代碼:
1 #include <iostream> 2 #include <algorithm> 3 #include <cstdio> 4 #include <cmath> 5 using namespace std; 6 7 struct Node{ 8 int l,r; 9 long long Max; 10 }node[100005*4]; 11 long long v[100005]; 12 long long x[100005]; 13 long long dp[100005]; 14 const double PI = acos(-1.0); 15 16 void build(int id,int l,int r){ 17 int mid = (l+r)>>1; 18 node[id].l = l; 19 node[id].r = r; 20 if(l == r){ 21 node[id].Max = 0; 22 return ; 23 } 24 build(id*2,l,mid); 25 build(id*2+1,mid+1,r); 26 27 node[id].Max = max(node[id*2].Max,node[id*2+1].Max); 28 } 29 30 void update(int id,int k,long long p){ //更新 k 處的值爲 p 31 int ll = node[id].l; 32 int rr = node[id].r; 33 int mid = (ll+rr)>>1; 34 35 if(ll == rr){ 36 node[id].Max = p; 37 return ; 38 } 39 40 if(k <= mid) update(id*2,k,p); 41 else 42 update(id*2+1,k,p); 43 node[id].Max = max(node[id*2].Max,node[id*2+1].Max); 44 } 45 46 long long query(int id,int l,int r){ 47 int ll = node[id].l; 48 int rr = node[id].r; 49 int mid = (ll+rr)>>1; 50 51 if(l > r) return 0; 52 53 if(ll== l && rr == r) 54 return node[id].Max; 55 else if(r <= mid) 56 return query(id*2,l,r); 57 else if(l > mid) 58 return query(id*2+1,l,r); 59 else 60 return max(query(id*2,l,mid),query(id*2+1,mid+1,r)); 61 } 62 int main() 63 { 64 int n; 65 while(cin>>n){ 66 long long r,h; 67 for(int i = 1;i <= n;i ++){ 68 scanf("%I64d%I64d",&r,&h); 69 v[i] = r*r*h; 70 dp[i] = v[i]; 71 x[i] = v[i]; 72 } 73 sort(x+1,x+n+1); 74 long long ans = 0; 75 build(1,1,n); 76 for(int i = 1;i <= n;i ++){ 77 int cur = lower_bound(x+1,x+n+1,v[i]) - x; //前閉後開區間找大於或等於 v[i]的第一個位置。 78 //wa了很久都不知道爲啥。 79 dp[i] = max(dp[i],query(1,1,cur-1)+v[i]); 80 update(1,cur,dp[i]); 81 ans = max(ans,dp[i]); 82 } 83 printf("%.15f\n",ans*PI); 84 } 85 return 0; 86 }