zoukankan      html  css  js  c++  java
  • 629D

    题意:给定n个圆柱体的半径和高,输入顺序即圆柱体的编号顺序。现在规定,只有编号和体积均大于另一个圆柱体,才能放到另一个圆柱体的体积上面。求能叠加的最大体积是多少。

    酝酿了我三天,才理解。自己敲个代码,还超时了,但是把思路记录一下吧,实在不知道哪里超时了。

    思路:dp+线段树维护。本质是求递增序列的最大和。设dp[i]表示以编号为i的圆柱体为顶部的圆柱。大问题拆分成子问题:dp[i]=max(dp[j])  +  v[i] ,j表示可以放在i号圆柱体下的合法圆柱体,即体积和编号均小于 i 。但是如果直接枚举状态,然后 去暴力搜索合法的 dp[j],会超时,因此,第二层for循环,合法的dp[j]用线段树维护(但是我还是超时了uhnnnnnnn,,无语啊)。先确定要维护的区间,维护区间为v即每个圆柱体的体积,再把体积从小到大排序。再去遍历状态参量  i  ,每一次找到 v[i]在体积区间当中所处的位置。然后在体积区间里小于v[i]的部分里找最大的dp[j]。其实一开始我有个地方不理解,就是只维护体积区间,每次去查1至 i-1 区间里的最大的dp[j],但是我觉得编号不一定满足 j<i,事实证明想多了,因为每一次更新v[i]所处位置的dp[i]值时,,是按照编号顺序来更新的,也就是说哪些体积比它小,但是编号比他大的在后面才会更新,当前这步是不会更新的。

    本题,线段树的精髓,每当求出一个位置的dp[i]的时候,都去包含此位置的区间,并且由于还是按照输入顺序来更新的,所以不存在体积小,但是序号大的情况。

    上个超时代码吧。

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    typedef long long ll;
    
    
    struct Node
    {
        int l,r;
        int dat;
    }t[100000*4];
    
    long long dp[100000*4];
    long long v[100000*4];
    int H[100000*4];
    long long ans=0;
    const double PI=acos(-1.0);
    int n;
    
    void build(int p,int l,int r)
    {
        t[p].l=l,t[p].r=r;
        //int mid=(l+r)>>1;
        if(l==r){ t[p].dat=0;return;}
        int mid=(l+r)>>1;
        build(p*2,1,mid);
        build(p*2+1,mid+1,r);
        t[p].dat=max(t[p*2].dat,t[p*2+1].dat);
    }
    
    ll query(int p,int l,int r)
    {
        if(l>r) return 0;
        if(l<=t[p].l&&t[p].r<=r) return t[p].dat;
        int mid=(t[p].l+t[p].r)>>1;
        ll val=-1<<30;
        if(mid>=l) val=max(val,query(p*2,l,r));
        if(mid<r) val=max(val,query(p*2+1,l,r));
        return val;    
    }
    
    void update(int p,int x,int v)
    {
        if(t[p].l==t[p].r){t[p].dat=v;return;}
        int mid=(t[p].l+t[p].r)>>1;
        if(x<=mid) update(p*2,x,v);
        else update(p*2+1,x,v);
        t[p].dat=max(t[p*2].dat,t[p*2+1].dat);
    }
    
    
    int main()
    {
        cin>>n;
        int r,h;
        for(int i=1;i<=n;i++)
        {
        cin>>r>>h;
        v[i]=r*r*h;
        H[i]=v[i];
        dp[i]=v[i];
        }
        
        sort(H+1,H+1+n);
        build(1,1,n);
        for(int i=1;i<=n;i++)
        {
            int cur=lower_bound(H+1,H+1+n,v[i])-H;
            dp[i]=max(dp[i],query(1,1,cur-1)+v[i]);
            update(1,cur,dp[i]);
            ans=max(ans,dp[i]);
        }
        
        printf("%.15lf",PI*ans);
     return 0;    
    } 
  • 相关阅读:
    记支付宝接口对接,涉及到提取证书SN号的解决方案
    Second Level Cache for Entity Framework 6.1
    记一个dynamic的坑
    使用EntityFramwork[6.1]进行级联保存的时候出现异常
    转:Transform Web.Config when Deploying a Web Application Project
    转:程序员如何增加收入
    超实用的JavaScript技巧及最佳实践(下)
    超实用的JavaScript技巧及最佳实践(上)
    Oracle PL/SQL入门语法点
    轻量级IOC框架:Ninject (下)
  • 原文地址:https://www.cnblogs.com/rainyskywx/p/10719472.html
Copyright © 2011-2022 走看看