zoukankan      html  css  js  c++  java
  • HDU-4719--Oh My Holy FFF(线段树优化DP)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4719

    题目大意:有n个人,第$i$个人的身高为$h_i$,现在要把这些人按照原来的顺序分为连续的若干段,要求每组的人数不超过$l$,同时,我们这每组的最后一个人身高为$b_i$,则有$b_i>b_{i-1}(b_0=0)$,现在我们设每种分组方案的价值为$sum b_{i}^{2}-b_{i-1}$,问能够得到的最大价值是多少?

    Sample Input

    2
    5 2
    1 4 3 2 5
    5 2
    5 4 3 2 1

    Sample Output

    Case #1: 31
    Case #2: No solution

    实际上最朴素的DP不难想到,设dp[i]表示前i个人分成若干组的最大价值,那么则有$dp[i]=max_{j=[i-l,i-1]}{dp[j]+h_i^2-h_j}$

    那么代码也就不难写出来了:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int mac=1e5+10;
    
    int dp[mac],h[mac];
    
    int main()
    {
        int t,Case=0;
        scanf ("%d",&t);
        while (t--){
            int n,m;
            scanf ("%d%d",&n,&m);
            for (int i=1; i<=n; i++)
                scanf ("%d",&h[i]);
            memset(dp,0,sizeof dp);
            dp[1]=h[1]*h[1];
            for (int i=1; i<=n; i++){
                for (int j=max(1,i-m); j<i; j++){
                    if (h[j]>=h[i]) continue;
                    dp[i]=max(dp[i],dp[j]+h[i]*h[i]-h[j]);
                }
            }
            if (!dp[n]) {printf("Case #%d: No solution
    ",++Case);}
            else {
                printf("Case #%d: %d
    ",++Case,dp[n]);
            }
        }
    
        return 0;
    }
    View Code

    只不过这样的话时间的复杂度会很高,就会导致T。。。

    事实上将上面的式子变化一下就是:$dp[i]=h_i^2+max_{j=[i-l,i-1]}{dp[j]-h_j}$

    而$max_{j=[i-l,i-1]}{dp[j]-h_j}$这个东西事实上可以用线段树来维护的,我们需要知道的是题目对顺序的要求,所以我们可以将他们的pos直接同步线段树的pos,那么这样一来查找的时候我们直接$query(1,n,1,pos[i]-l,pos[i]-1)$就可以了。那么怎么维护$b_i>b_{i-1}$呢,我们将其排序就好了,按照身高的升序排列,如果身高一样,则按照pos降序排列。因为后面的pos并不能影响前面的。

    值得注意的是边界id的处理和爆int

    以下是AC代码:

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    using namespace std;
    
    const int mac=1e5+10;
    #define lson l,mid,rt<<1
    #define rson mid+1,r,rt<<1|1
    #define lc rt<<1
    #define rc rt<<1|1
    typedef long long ll;
    
    struct node
    {
        int id,h;
        bool operator <(const node &a)const{
            if (h==a.h) return id>a.id;
            return h<a.h;
        }
    }a[mac];
    
    ll dp[mac];
    ll tree[mac<<2];
    
    void update(int l,int r,int rt,int pos,ll val)
    {
        if (l==r){
            tree[rt]=val;
            return;
        }
        int mid=(l+r)>>1;
        if (mid>=pos) update(lson,pos,val);
        else  {update(rson,pos,val);}
        tree[rt]=max(tree[lc],tree[rc]);
    }
    
    ll query(int l,int r,int rt,int L,int R)
    {
        ll ans=-1;
        if (l>=L && r<=R) return tree[rt];
        int mid=(l+r)>>1;
        if (mid>=L) ans=max(ans,query(lson,L,R));
        if (mid<R) ans=max(ans,query(rson,L,R));
        return ans;
    }
    
    int main()
    {
        int t,Case=0;
        scanf ("%d",&t);
        while (t--){
            int n,m,mx=0;
            scanf ("%d%d",&n,&m);
            for (int i=1; i<=n; i++){
                int x;
                scanf ("%d",&x);
                a[i]=node{i+1,x};
            }
            sort(a+1,a+1+n);n++;
            memset(dp,0,sizeof dp);
            memset(tree,-1,sizeof tree);
            ll ans=-1;
            update(1,n,1,1,0);
            for (int i=1; i<=n; i++){
                ll p=query(1,n,1,max(1,a[i].id-m),a[i].id-1);
                if (p==-1) {
                    if (a[i].id==n) break;
                    continue;
                }
                dp[i]=1LL*a[i].h*a[i].h+p;
                if (a[i].id==n){
                    ans=dp[i];
                    break;
                } 
                update(1,n,1,a[i].id,dp[i]-a[i].h);
            }
            if (ans==-1) printf("Case #%d: No solution
    ",++Case);
            else printf("Case #%d: %lld
    ",++Case,ans);
        }
    
        return 0;
    }
    路漫漫兮
  • 相关阅读:
    QML控件设置style样式
    QML:ListElement: cannot use script for property value
    内存更换乌龙事件
    服务器的寿命到底有多长
    这些年渠道管理系统上发生的那些事
    IT囧事之误删测试环境的生产库
    旁观一个软件产品的终结
    一根网线引发的血案
    论代码规范命名的重要性
    服务器故障之内存损坏
  • 原文地址:https://www.cnblogs.com/lonely-wind-/p/13245743.html
Copyright © 2011-2022 走看看