bzoj3594 [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

 

正解:$dp$+二维树状数组优化。

首先有一个显然的结论,就是每次拔玉米肯定是从一个点开始一直拔到$n$,这样肯定是不会差的。

然后我们就可以$dp$了,设$f[i][j]$表示前$i$个点,拔高$j$次玉米的最大玉米数。

然后$dp[i][j]=max(dp[k][p])+1$,当$a[k]\leq a[i]+j-p$时成立。

移项以后可以得到$a[k]+p\leq a[i]+j$,于是我们维护一个二维树状数组的前缀最大值就行了。

 

 1 #include <bits/stdc++.h>
 2 #define il inline
 3 #define RG register
 4 #define ll long long
 5 #define lb(x) (x & -x)
 6 #define max(a,b) (a>b ? a : b)
 7 
 8 using namespace std;
 9 
10 int c[6000][510],a[10010],sz,n,k;
11 
12 il int gi(){
13   RG int x=0,q=1; RG char ch=getchar();
14   while ((ch<'0' || ch>'9') && ch!='-') ch=getchar();
15   if (ch=='-') q=-1,ch=getchar();
16   while (ch>='0' && ch<='9') x=x*10+ch-48,ch=getchar();
17   return q*x;
18 }
19 
20 il void add(RG int x,RG int y,RG int v){
21   for (RG int i=x;i<=sz;i+=lb(i))
22     for (RG int j=y;j<=k;j+=lb(j)) c[i][j]=max(c[i][j],v);
23   return;
24 }
25 
26 il int query(RG int x,RG int y){
27   RG int res=0;
28   for (RG int i=x;i;i^=lb(i))
29     for (RG int j=y;j;j^=lb(j)) res=max(res,c[i][j]);
30   return res;
31 }
32 
33 int main(){
34 #ifndef ONLINE_JUDGE
35   freopen("corn.in","r",stdin);
36   freopen("corn.out","w",stdout);
37 #endif
38   n=gi(),k=gi()+1;
39   for (RG int i=1;i<=n;++i) a[i]=gi(),sz=max(sz,a[i]); sz+=k;
40   for (RG int i=1;i<=n;++i)
41     for (RG int j=k;j;--j) add(a[i]+j,j,query(a[i]+j,j)+1);
42   printf("%d\n",query(sz,k)); return 0;
43 }

 

posted @ 2017-10-24 22:34  wfj_2048  阅读(160)  评论(0编辑  收藏  举报