• [SCOI2014]方伯伯的玉米田


    洛谷题目链接

    动态规划:

    首先,仔细看题目明确一点,如果要拔高,无论怎么拔,拔高的区间右端点一定是$n$,为什么呢?

    这样做:

    $1、$对于区间左边,不会减小以前的最优决策

    $2、$对于区间内,两两之间相对高度不会发生变化

    $3、$对于区间右边,会减小它们进入最优序列的可能性

    所以操作区间在右端点就可以解决第三个问题

    那么考虑$dp$:

    设$f[i][j]$表示前面$i$个中拔高了$j$次,最多的保留数

    状态转移也非常明显:$$f[i][j]=max(f[k][l])+1$$

    显然需要一个可以快速求出二维最大值的数据结构

    这里用的树状数组,直接套上模板,查询区间最大值即可

    代码:

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #define N 10007
    #define K 507
    #define M 6000
    #define lowbit(x) x&(-x)
    using namespace std;
    int n,k,maxn,ans;
    int val[N],tree[M][K];
    void Update(int pos,int val,int h)
    {
        for(;pos<=maxn+k;pos+=lowbit(pos))
            for(int i=h;i<=k+1;i+=lowbit(i))
            	tree[pos][i]=max(tree[pos][i],val);
    }
    int Search(int pos,int h)
    {
        int ans=0;
        for(;pos;pos-=lowbit(pos))
            for(int i=h;i;i-=lowbit(i))
            	ans=max(ans,tree[pos][i]);
        return ans;
    }
    int main()
    {
        scanf("%d%d",&n,&k);
        for(int i=1;i<=n;++i)
        {
            scanf("%d",&val[i]);
            maxn=max(maxn,val[i]);
        }
        for(int i=1;i<=n;++i)
            for(int j=k;j>=0;--j)
            {
                int x=Search(val[i]+j,j+1)+1; 
                ans=max(ans,x);
                Update(val[i]+j,x,j+1);
            }
        printf("%d",ans);
        return 0;
    }
    

      

  • 相关阅读:
    算法练习题
    牛XX面试题
    web前端面试题
    在js中什么情况下会返回undefined
    yarn
    Web 开发技巧
    dll 文件创建与使用
    【转】 VS2008在64位Windows平台上编译ArcEngine导致HRESULT:0x80040154 (REGDB_E_CLASSNOTREG)错误的解决办法
    Googlemap获取经纬度For APIV3
    javascript局部变量/全局变量
  • 原文地址:https://www.cnblogs.com/yexinqwq/p/10263754.html
Copyright © 2020-2023  润新知