Codeforces Round #343 (Div. 2) D - Babaei and Birthday Cake 线段树+DP
题意:做蛋糕,给出N个半径,和高的圆柱,要求后面的体积比前面大的可以堆在前一个的上面,求最大的体积和。
思路:首先离散化蛋糕体积,以蛋糕数量建树建树,每个节点维护最大值,也就是假如节点i放在最上层情况下的体积最大值dp[i]。每次查询比蛋糕i小且最大体积的蛋糕,然后更新线段树。注意此题查询的技巧!!查询区间不变l,r,才能保证每次查到的是小且最大体积。
1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cstdio> 6 #include<set> 7 #include<map> 8 #include<vector> 9 #include<cstring> 10 #include<stack> 11 #include<cmath> 12 #include<queue> 13 #define clc(a,b) memset(a,b,sizeof(a)) 14 #include <bits/stdc++.h> 15 using namespace std; 16 #define LL long long 17 const int maxn = 1e5 + 10; 18 const int inf=0x3f3f3f3f; 19 const double pi=acos(-1); 20 double dp[maxn]; 21 double v[maxn],f[maxn]; 22 int num[maxn]; 23 struct node 24 { 25 double r,h; 26 } p[maxn]; 27 28 double V(node a) 29 { 30 return a.r*a.r*a.h*pi; 31 } 32 33 struct Node 34 { 35 int l,r; 36 double maxx; 37 } tree[100010*4]; 38 39 void pushup(int cnt) 40 { 41 tree[cnt].maxx=max(tree[cnt<<1].maxx,tree[cnt<<1|1].maxx); 42 } 43 44 void b_tree(int l,int r,int rt) 45 { 46 tree[rt].l=l; 47 tree[rt].r=r; 48 if(l==r) 49 { 50 tree[rt].maxx=0.0; 51 return ; 52 } 53 int mid=(l+r)>>1; 54 b_tree(l,mid,rt<<1); 55 b_tree(mid+1,r,rt<<1|1); 56 pushup(rt); 57 } 58 59 double query(int l,int r,int rt) 60 { 61 if(tree[rt].l>=l&&tree[rt].r<=r) 62 { 63 return tree[rt].maxx; 64 } 65 int mid=(tree[rt].l+tree[rt].r)>>1; 66 double ans=0.0; 67 if(l<=mid) 68 ans=max(ans,query(l,r,rt<<1)); 69 if(r>mid) 70 ans=max(ans,query(l,r,rt<<1|1)); 71 return ans; 72 } 73 74 void update(int x,double val,int rt) 75 { 76 if(tree[rt].l==x&&tree[rt].r==x) 77 { 78 tree[rt].maxx=max(tree[rt].maxx,val); 79 return; 80 } 81 int mid=(tree[rt].l+tree[rt].r)>>1; 82 if(x<=mid) 83 update(x,val,rt<<1); 84 else 85 update(x,val,rt<<1|1); 86 pushup(rt); 87 } 88 89 int main() 90 { 91 int n; 92 while(cin>>n) 93 { 94 b_tree(1,n,1); 95 clc(dp,0); 96 for(int i=0; i<n; i++) 97 { 98 scanf("%lf%lf",&p[i].r,&p[i].h); 99 v[i]=V(p[i]); 100 f[i]=v[i]; 101 } 102 sort(f,f+n); 103 for(int i=0; i<n; i++) 104 { 105 num[i]=lower_bound(f,f+n,v[i])-f+1; 106 } 107 for(int i=0; i<n; i++) 108 { 109 if(num[i]-1==0) 110 dp[i]=v[i]; 111 else 112 dp[i]=query(1,num[i]-1,1)+v[i]; 113 update(num[i],dp[i],1); 114 } 115 double ans=0.0; 116 for(int i=0; i<n; i++) 117 ans=max(ans,dp[i]); 118 printf("%.10f\n",ans); 119 } 120 return 0; 121 }