• AcWing3662-最大上升子序列和(树状数组优化dp+离散化)


    link

    思路:

    数据范围是(1e5).
    先回想数据范围为(1e3)的做法:
    (dp[i])表示以第i个数为结尾的最大上升子序列和,转移就是(dp[i]=max(dp[j]+w[i]),1<=j<i)
    时间复杂度(O(n^{2}))
    这题显然过不去,考虑用数据结构优化。
    每次转移过来的都是前缀的最大值,可以用树状数组维护,时间复杂度变为(O(nlogn))
    由于本题数据范围很大,还需要离散化。

    代码:

    #include<bits/stdc++.h>
    
    using namespace std;
    
    typedef long long LL;
    
    const int N = 1e5+10;
    
    LL n,tr[N],a[N],dp[N];
    vector<LL>nums;
    
    LL lowbit(LL x)
    {
        return x & -x;
    }
    
    void update(LL x, LL c) 
    {
        for (int i = x; i <= n; i += lowbit(i)) tr[i] = max(tr[i],c);
    }
    
    LL query(LL x)  
    {
        LL res = 0;
        for (int i = x; i; i -= lowbit(i)) res =max(res, tr[i]);
        return res;
    }
    
    
    int main()
    {
        cin>>n;
        for (int i = 1; i <= n; i ++ ){
            cin>>a[i];
            nums.push_back(a[i]);
        }
        sort(nums.begin(),nums.end());
        nums.erase(unique(nums.begin(),nums.end()),nums.end());
        LL res=0;
        for (int i = 1; i <= n; i ++ ){
            int t=lower_bound(nums.begin(),nums.end(),a[i])-nums.begin()+1;
            ///使下标从1开始
            dp[i]=query(t-1)+a[i];
            res=max(res,dp[i]);
            update(t,dp[i]);
        }
        cout<<res<<endl;
        return 0;
    }
    
    
  • 相关阅读:
    ubuntu下手动安装autoconf
    解决VMware下的ubuntu桌面鼠标键盘失效的问题
    DP搬运工1
    把数字转换成货币格式
    指定字符隐藏
    JS 时间获取 (常用)
    electron 安装
    el-form表单校验包含循环
    算法-07| 动态规划
    纯手撸——归并排序
  • 原文地址:https://www.cnblogs.com/OvOq/p/14880951.html
Copyright © 2020-2023  润新知