Codeforces Round #343 (Div. 2) D

题意:做蛋糕,给出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
",ans);
119     }
120     return 0;
121 }
View Code
原文地址:https://www.cnblogs.com/ITUPC/p/5212674.html