zoukankan      html  css  js  c++  java
  • [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;
    }
    

      

  • 相关阅读:
    HDU 2955 Robberies
    CodeForces 429B Working out DP
    Lweb and String 超级大水题
    A water problem 大数取余。
    Danganronpa 水题。
    HDU 2018 DP
    Git分支管理
    linux相关操作命令
    项目部署相关命令(pm2)
    ubantu16.04安装sougou输入法
  • 原文地址:https://www.cnblogs.com/yexinqwq/p/10263754.html
Copyright © 2011-2022 走看看