zoukankan      html  css  js  c++  java
  • hdu4719 线段树优化dp

    hdu4719 Oh My Holy FFF

    题意

    有一个长度为(n(1leq nleq 100000))的数列(a),将这个数列划分成几个子序列,每个子序列的长度不超过(L(1leq Lleq n)),并且每个子序列的最后一个元素严格单调递增。对于一种划分数为(k)的方案,设每个子序列的最后一个元素是(b[i](1leq ileq k))(b[0]=0),则这个划分方案的得分为(sum (b[i]^2-b[i-1])),计算对于序列的合法划分所能得到的最大得分。

    题解

    (f[i])表示以第(i)个元素结尾所能得到的最大得分,则(f[i]=max(f[j]+a[i]^2-a[j])),其中(i-Lleq jleq i-1)并且(a[j]<a[i])
    可以将(f[j]+a[i]^2-a[j])拆成((f[j]-a[j]))(a[i]^2)两部分,其中(a[i]^2)(i)本身决定,无法改变,((f[j]-a[j]))可以放进线段树查找,得到满足(i-Lleq jleq i-1)的最大值。
    对于(a[j]<a[i])这个限制条件,可以通过更改计算顺序来实现。将(a[i])从小到大排序,逐个插入线段树中,这样线段树中的(a[j])全部小于当前计算的(a[i]),所以(a[i])一定是由比它小的(a[j])转移过来的。

    #include<bits/stdc++.h>
    #define LL long long
    using namespace std;
    
    const int maxn=100010;
    int T,n,L;
    LL tree[4*maxn],dp[maxn];
    
    struct node{
        int id;
        LL x;
        bool operator < (const node& t)const{
            if(x!=t.x) return x<t.x;
            return id>t.id;
        }
    }a[maxn];
    
    void pushup(int o){
        tree[o]=max(tree[o<<1],tree[o<<1|1]);  
    }
    
    void build(int o,int l,int r){
        if(l==r){
            tree[o]=-1;
            return;
        }
        int mid=(l+r)>>1;
        build(o<<1,l,mid);
        build(o<<1|1,mid+1,r);
        pushup(o);
    }
    
    void change(int o,int l,int r,int pos,LL v){
        if(l==r){
            tree[o]=v;
            return;
        }
        int mid=(l+r)>>1;
        if(pos<=mid) change(o<<1,l,mid,pos,v);
        else change(o<<1|1,mid+1,r,pos,v);
        pushup(o);
    }
    
    LL query(int o,int l,int r,int ql,int qr){
        if(ql<=l && r<=qr) return tree[o];
        int mid=(l+r)>>1;
        LL ans=-1;
        if(ql<=mid) ans=max(ans,query(o<<1,l,mid,ql,qr));
        if(qr>mid) ans=max(ans,query(o<<1|1,mid+1,r,ql,qr));
        return ans;
    }
    
    int main(){
        scanf("%d",&T);
        for(int cas=1;cas<=T;cas++){
            scanf("%d %d",&n,&L);
            for(int i=1;i<=n;i++){
                scanf("%lld",&a[i].x);
                a[i].id=i;
            }
            build(1,0,n);
            change(1,0,n,0,0);
            sort(a+1,a+1+n);
            for(int i=1;i<=n;i++){
                dp[a[i].id]=-1;
                LL t=query(1,0,n,max(0,a[i].id-L),a[i].id-1);
                if(t==-1) continue;
                dp[a[i].id]=t+a[i].x*a[i].x;
                change(1,0,n,a[i].id,dp[a[i].id]-a[i].x);
            }
            printf("Case #%d: ",cas);
            if(dp[n]==-1) printf("No solution
    ");
            else printf("%lld
    ",dp[n]);
        }
    }
    
  • 相关阅读:
    HashMap_经典存储_经典分拣思路
    (GOF23设计模式)_单例模式_应用场景_饿汉式_懒汉式
    sql简单测试
    Java概述
    搭建集群时的问题总结
    在Java连接hbase时出现的问题
    JavaAPI与hbase的交互
    Resourcemanager的高可用
    hbase安装
    hbase报错org.apache.hadoop.hbase.TableExistsException: hbase:namespace
  • 原文地址:https://www.cnblogs.com/fxq1304/p/14586858.html
Copyright © 2011-2022 走看看