zoukankan      html  css  js  c++  java
  • dp+树状数组(最长上升子序列+树状数组)

    There are N flowers arranged in a row. For each i (1iN), the height and the beauty of the i-th flower from the left is hihi and aiai, respectively. Here, h1,h2,,hN are all distinct.

    Taro is pulling out some flowers so that the following condition is met:

    • The heights of the remaining flowers are monotonically increasing from left to right.

    Find the maximum possible sum of the beauties of the remaining flowers.

    Constraints

     

    • All values in input are integers.
    • 1N2×1e5
    • 1hiN
    • h1,h2,,hN are all distinct.
    • 1ai1e9

    Input

     

    Input is given from Standard Input in the following format:

    NN
    h1 h2  hN
    a1 a2  aN
    

    Output

     

    Print the maximum possible sum of the beauties of the remaining flowers.

    Sample Input 1

     

    4
    3 1 4 2
    10 20 30 40
    

    Sample Output 1

     

    60
    

    We should keep the second and fourth flowers from the left. Then, the heights would be 1,21,2 from left to right, which is monotonically increasing, and the sum of the beauties would be 20+40=6020+40=60.

    Sample Input 2

     

    1
    1
    10
    

    Sample Output 2

     

    10
    

    The condition is met already at the beginning.

    Sample Input 3

     

    5
    1 2 3 4 5
    1000000000 1000000000 1000000000 1000000000 1000000000
    

    Sample Output 3

     

    5000000000
    

    The answer may not fit into a 32-bit integer type.

    Sample Input 4

     

    9
    4 2 5 8 3 6 1 7 9
    6 8 8 4 6 3 5 7 5
    

    Sample Output 4

     

    31
    

    We should keep the second, third, sixth, eighth and ninth flowers from the left.

    题意:

    给你 h数组和s数组
    问你 h数组一直上升的序列中 s数组最大的和是多少

    这个题就是dp[i]代表的是前i朵花,并且取第i朵的最大和,那么转移方程就是dp[i]=dp[j]+v[i](j<i,a[j]<a[i])

    注意这个答案不是dp[n]而是max(dp[1],dp[2],dp[3]........)

    然后如果你普通的写就是:

    for(int i = 1;i<=n;++i)
        {
            for(int j = 1;j<i;++j)
            {
                if(h[i]>h[j])
                {
                    dp[i] = max(dp[i],dp[j]+arr[i]);
                    ans = max(ans,dp[i]);
                }
            }
       }

    这样肯定会超时的,所以你可以用线段树或者树状数组来维护1到i-1的dp数组的最大值

    线段树:

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    typedef long long ll; 
    using namespace std;
    int n;
    const int maxn=5e6+100;
    ll h[maxn];
    ll a[maxn];
    ll dp[maxn];//dp[i]为前i个的最大值 
    struct node{
        int l,r;
        ll ma;
    }t[maxn];
    void build(int p,int l,int r){
        t[p].l=l;
        t[p].r=r;
        if(l==r){
            return ;
        }
        int mid=(t[p].l+t[p].r)/2;
        build(2*p,l,mid);
        build(2*p+1,mid+1,r);
    }
    void update(int p,int x,ll k){
        if(t[p].r==t[p].l){
            t[p].ma=k;
            return ;
        }
        int mid=(t[p].l+t[p].r)/2;
        if(x<=mid){
            update(2*p,x,k);
        }
        else{
            update(2*p+1,x,k);
        }
        t[p].ma=max(t[2*p].ma,t[2*p+1].ma);
    } 
    ll query(int p,int l,int r){
        if(l<=t[p].l&&r>=t[p].r){
            return t[p].ma;
        }
        ll ans=-1e18;
        int mid=(t[p].l+t[p].r)/2;
        if(l<=mid){
            ans=max(ans,query(2*p,l,r));
        } 
        if(r>mid){
            ans=max(ans,query(2*p+1,l,r));
        } 
        return ans;
    }
    int main(){
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>h[i]; 
        }
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        build(1,1,2e5+10);
        ll ma=0; 
        for(int i=1;i<=n;i++){
            ll z=query(1,1,h[i]); 
            dp[i]=(1ll)*(z+a[i]);
            update(1,h[i],dp[i]);
            ma=max(ma,dp[i]);
        }
        cout<<ma<<endl;
    } 
    /*
    4
    1 2 3 2 3
    1 1 1 2 3
    */

    树状数组:

    #include<iostream>
    #include<algorithm>
    using namespace std;
    typedef long long ll; 
    const int maxn=1e6+100;
    ll dp[maxn];
    int h[maxn];
    ll a[maxn];
    ll ans[maxn];
    int n;
    ll lowbit(int x){
        return x&-x;
    }
    void add(int x,ll k){
        for(int i=x;i<=n;i+=lowbit(i)){
            ans[i]=max(ans[i],k);
        } 
    }
    ll query(int x){
        ll z=0;
        for(int i=x;i>0;i-=lowbit(i)){
            z=max(z,ans[i]);
        } 
        return z;
    } 
    int main(){
        cin>>n;
        for(int i=1;i<=n;i++){
            cin>>h[i];
        }
        for(int i=1;i<=n;i++){
            cin>>a[i];
        }
        ll ma=0;
        for(int i=1;i<=n;i++){
            dp[i]=a[i]+query(h[i]);
            ma=max(ma,dp[i]);
            add(h[i],dp[i]); 
        }
        cout<<ma<<endl;
    }
  • 相关阅读:
    Android 程序架构: MVC、MVP、MVVM、Unidirectional、Clean...
    asp.net发布到IIS中出现错误:处理程序“PageHandlerFactory-Integrated”在其模块列表中有一个错误模块“ManagedPipelineHandler”
    反射中使用 BindingFlags.IgnoreCase
    JQuery判断数组中是否包含某个元素$.inArray("js", arr);
    Sql日期时间格式转换
    c#组元(Tuple)的使用
    逆向最大匹配分词算法C#
    [WEB API] CLIENT 指定请求及回应格式(XML/JSON)
    Jquery 将表单序列化为Json对象
    JS调试加断点
  • 原文地址:https://www.cnblogs.com/lipu123/p/14515182.html
Copyright © 2011-2022 走看看