【BZOJ3594】【SCOI2014】方伯伯的玉米田

来源:互联网 发布:大闹天空坐骑进阶数据 编辑:程序博客网 时间:2024/05/16 10:33

方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美。
这排玉米一共有 n 株,它们的高度参差不齐。
方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感的玉米拔除掉,使得剩下的
玉米的高度构成一个单调不下降序列。
方伯伯可以选择一个区间,把这个区间的玉米全部拔高 1 单位高度,他可以进行最多 K 次这样的操作。
拔玉米则可以随意选择一个集合的玉米拔掉。
问能最多剩多少株玉米,来构成一排美丽的玉米。
【输入】
第 1 行包含 2 个整数 n, K,分别表示这排玉米的数目以及最多可进行多少次操作。
第 2 行包含 n 个整数,第 i 个数表示这排玉米,从左到右第 i 株玉米的高度 a i 。
【输出】
输出 1 个整数,最多剩下的玉米数。
【样例输入】
3 1
2 1 3
【样例输出】
3
【数据范围】
对于 10% 的数据,1 ≤ n ≤ 1000, 1 ≤ K ≤ 100
对于 100% 的数据,1 ≤ n ≤ 10000, 1 ≤ K ≤ 500, 1 ≤ a i ≤ 5000

【崩批】
咋作为一枚蒟蒻,放水题一道来作为blog 的第一道题吧。可是我当时并没有写出来。。。。
首先我们不难想到每一次进行区间拔高都可以以拔高区间[i,n]达到最佳方案,然后很容易想到一个DP,定义F[i,j]表示前i个玉米一共拔高j次所能获得的最大不下降子序列的长度。那么转移为:
F[i,j] = max(F[x,y])+1
其中x<i,y<=j。那么仅仅当Ai+j>=Ax+y的时候我们进行这个转移。j和y是需要枚举的那么时间复杂度就为O(n^2*k^2);
然后我们可以选择用树状数组或者线段树去维护区间Ax+y<=Ai+j && y<=j的最大F值。然后就。。。没有然后了。

#include<cstdio>#include<cstdlib>#include<algorithm>#include<cstring>using namespace std;const int Maxn = 10000+10;const int Maxk = 500+10;int F[Maxn][Maxk],N,K;int C[Maxn][Maxk],A[Maxn];int max(int a,int b){if(a>b)return a;return b;}int lowbit(int x){return x&-x;}void change(int n,int m,int w){    for(int x=n;x<=6000;x+=lowbit(x))      for(int y=m;y<=K+1;y+=lowbit(y)){        C[x][y] = max(C[x][y],w);      }}int query(int n,int m){    int ret=0;    for(int x=n;x;x-=lowbit(x))      for(int y=m;y;y-=lowbit(y)){        ret = max(ret,C[x][y]);      }    return ret;}void solve(){    scanf("%d%d",&N,&K);    for(int i=1;i<=N;i++) {scanf("%d",&A[i]);}    for(int i=1;i<=N;i++){        for(int j=0;j<=K;j++){            F[i][j] = query(A[i]+j+1,j+1)+1;        }        for(int j=0;j<=K;j++) change(A[i]+j+1,j+1,F[i][j]);    }    int ans=0;    for(int i=1;i<=N;i++) ans = max(ans,F[i][K]);    printf("%d\n",ans);}int main(){    solve();    return 0;}
0 0