zoukankan      html  css  js  c++  java
  • [SCOI2014]方伯伯的玉米田

    Description

    方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美。
    这排玉米一共有N株,它们的高度参差不齐。
    方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感的玉米拔除掉,使得剩下的玉米的高度构成一个单调不下降序列。
    方伯伯可以选择一个区间,把这个区间的玉米全部拔高1单位高度,他可以进行最多K次这样的操作。拔玉米则可以随意选择一个集合的玉米拔掉。
    问能最多剩多少株玉米,来构成一排美丽的玉米。

    Input


    第1行包含2个整数n,K,分别表示这排玉米的数目以及最多可进行多少次操作。
    第2行包含n个整数,第i个数表示这排玉米,从左到右第i株玉米的高度ai。

    Output


    输出1个整数,最多剩下的玉米数。

    Sample Input

    3 1
    2 1 3

    Sample Output

    3

    HINT

    1 < N < 10000,1 < K ≤ 500,1 ≤ ai ≤5000

    时限3S

    NK复杂度才5e6,3s时限,可以带两个log

    序列区间问题又比较容易带log

     

    考虑什么时候要拔高。

    一定是比前面矮,然后让它们长高一点。但是显然不要变得比后面高。

    所以,每次拔高的操作区间的右端点都是n!

    否则,右端点右面的部分只会贡献减少。

    然后就比较容易了。

    f[i][k]表示,前i个,以i结尾,包括i,一共拔高k次。

    转移:f[i][k]=max(f[j][l])+1 (j<i&&l<=k&&a[i]+k>=a[j]+l)

    j<i通过顺序可以保证。另外两个?
    a[i]只有5000,k只有500

    而且是一个二维前缀max

    所以二维树状数组即可。

     

    (注意,不一定以n结尾。所以是所有的f[i][k]取max)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=10000+5;
    const int M=505;
    int n,m;
    int t[5500+5][505];
    int a[N];
    int mx;
    void upda(int x,int y,int c){
        while(x<=mx){
            int p=y;
            while(p<=m+1){
                t[x][p]=max(t[x][p],c);
                p+=p&(-p);
            }
            x+=x&(-x);
        }
    }
    int query(int x,int y){
        int ret=0;
        while(x){
            int p=y;
            while(p){
                ret=max(ret,t[x][p]);
                p-=p&(-p);
            }
            x-=x&(-x);
        }
        return ret;
    }
    int f[N][M];
    int up[N];
    int main(){
        scanf("%d%d",&n,&m);
        for(int i=1;i<=n;i++) scanf("%d",&a[i]),mx=max(mx,a[i]+m);
        int ans=0;
        for(int i=1;i<=n;i++){
            int tmp=0;
            for(int k=0;k<=m;k++){
                f[i][k]=query(a[i]+k,k+1)+1;
                ans=max(ans,f[i][k]);
            }
            for(int k=0;k<=m;k++){
                upda(a[i]+k,k+1,f[i][k]);
            }
        }
        for(int k=0;k<=m;k++) ans=max(ans,f[n][k]);
        printf("%d",ans);
        return 0;
    }
  • 相关阅读:
    Valid Palindrome
    Path Sum II
    Reverse Integer
    Palindrome Number
    ZigZag Conversion
    函数调用堆栈 涉及汇编(转)
    关于字符指针和字符数组初始化的问题
    Remove Element(第一种方法参考别人)
    c内存分配(转)
    int *ptr=(int *)(&a+1)问题的探讨
  • 原文地址:https://www.cnblogs.com/Miracevin/p/9850508.html
Copyright © 2011-2022 走看看