【BZOJ3594】【SCOI2014】 方伯伯的玉米田
显然可以看出这是一道DP,然后就开始定义状态。。。
f[i][j]表示已经处理完i根玉米,拔高了j次,剩下的玉米的最大值。
f[i][j] = max{f[x][y]+1}(x<i,y<=j,h[x]+y<=h[i]+j)。
于是就可以用二维树状数组维护最大值了,第一维维护拔高次数,第二维维护拔高后的高度。
1 #include <iostream> 2 #include <cstdlib> 3 #include <cstdio> 4 #include <cstring> 5 6 using namespace std; 7 8 const int N = 10000 + 5; 9 10 int n, m, ans, h[N], f[N]; 11 12 struct Tree{ 13 int a[5510][510]; 14 Tree(){memset( a, 0, sizeof a );} 15 16 int lowbit( int x ){return x&(-x);} 17 18 void update( int X, int Y, int d ){ 19 for ( int x = X; x <= 5500; x += lowbit(x) ) 20 for ( int y = Y; y <= m+1; y += lowbit(y) ) 21 a[x][y] = max( a[x][y],d ); 22 } 23 int query( int X, int Y ){ 24 int ret = 0; 25 for ( int x = X; x; x -= lowbit(x) ) 26 for ( int y = Y; y; y -= lowbit(y) ) 27 ret = max( ret,a[x][y] ); 28 return ret; 29 } 30 }T; 31 int main(){ 32 scanf( "%d%d", &n, &m ); 33 for ( int i = 1; i <= n; i ++ ){ 34 int x; scanf( "%d", &x ); 35 for ( int j = m; j >= 0; j -- ){ 36 f[j] = T.query(x+j,j+1)+1; 37 ans = max( ans,f[j] ); 38 T.update(x+j,j+1,f[j]); 39 } 40 } 41 printf( "%d\n", ans ); 42 return 0; 43 }