[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;
}

 

posted @ 2018-10-25 16:09  *Miracle*  阅读(188)  评论(0编辑  收藏  举报