zoukankan      html  css  js  c++  java
  • CF-629 D

    • 求上升子序列的最大和。O(n^2)会暴力,在查询的时候要用线段树维护
    • 因为权值是浮点数,故先离散化一下,设第 i 个位置的权值,从小到大排名为 id。那么dp转移中 $$d[i] = max(d[i],d[i] + d[j])$$ 其中$$j<i & id[j]<id[i]$$ 故线段树结点区间[l,r]维护的是id = l 到 id = j 中的最大 dp值
    #include <bits/stdc++.h>
    using namespace std;
    const int N = 100000;
    double vol[N],r,h;
    int n,has[N],g[N],dp[N],tot;
    int c[N];
    vector<double> v;
    int getId(double a){
        return lower_bound(v.begin(),v.end(),a)-v.begin()+1;
    }
    struct Tree{
        int l,r;
        double data;
    }t[4*N];
    void build(int p,int l,int r){
        t[p].l = l;
        t[p].r = r;
        if(l==r){
            t[p].data = 0;return;
        }
        int mid = l+r>>1;
        build(p*2,l,mid);
        build(p*2+1,mid+1,r);
        t[p].data = 0;
    }
    void change(int p,int x,double val){
        if(t[p].l == t[p].r && t[p].l == x){
            t[p].data = max(t[p].data,val);
            return ;
        }
        int mid = (t[p].l+t[p].r)>>1;
        if(x<=mid)change(p*2,x,val);
        else change(p*2+1,x,val);
        t[p].data = max(t[p*2].data,t[p*2+1].data);
    }
    double ask(int p,int l,int r){
        if(t[p].l>=l&&t[p].r<=r)return t[p].data;
        int mid = (t[p].l+t[p].r)>>1;
        double val = 0;
        if(l<=mid)val = max(val,ask(p*2,l,r));
        if(r>mid)val = max(val,ask(p*2+1,l,r));
        return val;
    }
    int main(){
        cin>>n;
        for(int i=1;i<=n;i++){
            scanf("%lf%lf",&r,&h);
            vol[i] = acos(-1) * r * r * h;
            v.push_back(vol[i]);
        }
        sort(v.begin(),v.end());v.erase(unique(v.begin(),v.end()),v.end());
        build(1,1,n);
        double res = 0;
        for(int i=1;i<=n;i++){
            int id = getId(vol[i]);
            double now = ask(1,1,id-1);
            now = max(vol[i],vol[i]+now);
            res = max(res,now);
            change(1,id,now);
        }
        printf("%.10lf
    ",res);
        return 0;
    }
    
    • 辗转了很多次,惭愧,线段树做的题太少了

    法二:离散化+树状数组

    #include <bits/stdc++.h>
    using namespace std;
    const int N = 100010;
    const int inf = 0x3f3f3f3f;
    double vol[N],c[N];
    vector<double> v;
    int n,g[N];
    int getId(double res){
        return lower_bound(v.begin(),v.end(),res) - v.begin() + 1;
    }
    void add(int x,double y){
        c[x] = y;
        for(;x<=n;x+=x&-x)c[x] = max(c[x],y);
    }
    double ask(int x){
        double res = 0;
        for(;x;x-=x&-x)res = max(res,c[x]);
        return res;
    }
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            double r,h;
            scanf("%lf%lf",&r,&h);
            double vo = acos(-1) * r * r * h;
            vol[i] = vo;
            v.push_back(vo);
        }
        sort(v.begin(),v.end());v.erase(unique(v.begin(),v.end()),v.end());
        double res = 0;
        for(int i=1;i<=n;i++){
            int x = getId(vol[i]);
            double now = ask(x-1) + vol[i];
            add(x,now);
            res = max(res,now);
        }
        printf("%.10lf
    ",res);
        return 0;
    }
    

  • 相关阅读:
    C# WinForm判断Win7下程序是否以管理员身份运行
    C#设置文件(夹)权限
    验证字符串是否为有效的IP地址
    内存对齐
    C#线程启动时传入参数
    写字符串内容到文件
    Thread.Abort() Is Evil.
    如何优雅地控制线程状态
    C#读取文件,返回字符串形式的文件内容
    关于产生不重复随机数的算法 C#
  • 原文地址:https://www.cnblogs.com/1625--H/p/10661079.html
Copyright © 2011-2022 走看看