zoukankan      html  css  js  c++  java
  • 「2019冬令营提高组」全连

    传送门

    显然的 $dp$

    设 $f[i]$ 表示点击第 $i$ 个音符时的最大价值,$t[i]$ 表示音符 $i$ 的准备时间

    那么可以枚举 $1$ 到 $i-t[i]$ 的所有音符,如果  $j$ ,如果 $j+t[j]$ 小于等于 $i$ ,那么 $f[i]=max(f[i],f[j]+t[i]*val[i])$

    考虑优化转移

    显然如果 $i$ 在时间 $k$ 时可以转移,那么后面所有的时间也都能转移

    考虑用树状数组维护前缀最大值,用 $vector$ 维护时间 $k$ 时恰好可以转移的 $f$

    那么每次到一个位置就把可以转移的 $f$ 插到树状数组,然后查询最大值转移

    复杂度 $O(nlog_n)$,注意 $long long$

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cmath>
    #include<cstring>
    #include<vector>
    using namespace std;
    typedef long long ll;
    inline int read()
    {
        int x=0,f=1; char ch=getchar();
        while(ch<'0'||ch>'9') { if(ch=='-') f=-1; ch=getchar(); }
        while(ch>='0'&&ch<='9') { x=(x<<1)+(x<<3)+(ch^48); ch=getchar(); }
        return x*f;
    }
    const int N=1e6+7;
    int n,t[N],val[N];
    ll T[N],f[N],ans;
    inline void ins(int x,ll y) { while(x<=n) T[x]=max(T[x],y),x+=(x&-x); }
    inline ll query(int x) { ll res=0; while(x) res=max(res,T[x]),x-=(x&-x); return res; }
    vector <int> v[N];
    int main()
    {
        freopen("fc.in","r",stdin);
        freopen("fc.out","w",stdout);
        n=read();
        for(int i=1;i<=n;i++) t[i]=read();
        for(int i=1;i<=n;i++) val[i]=read();
        for(int i=1;i<=n;i++)
        {
            int len=v[i].size();
            for(int j=0;j<len;j++) ins(v[i][j], f[v[i][j]] );
            f[i]=1ll*val[i]*t[i]+ (i>t[i] ? query(i-t[i]) : 0);
            if(i+t[i]<=n) v[i+t[i]].push_back(i);
            ans=max(ans,f[i]);
        }
        printf("%lld",ans);
        return 0;
    }
  • 相关阅读:
    DAO层的作用
    JSP+DAO中servlet的作用
    Linux常用命令
    数据结构与算法之动态规划
    JVM之垃圾回收机制
    单例模式详解
    线程池基础知识
    解决Spring MVC Controller中输出中文出现的乱码问题
    LinkedList与ArrayList的get(int index)方法区别
    黄清山 | 2021软件代码开发技术作业五 | 代码开发、测试及发布
  • 原文地址:https://www.cnblogs.com/LLTYYC/p/10490457.html
Copyright © 2011-2022 走看看