bzoj3594: [Scoi2014]方伯伯的玉米田--树状数组优化DP

题目大意:对于一个序列,可以k次选任意一个区间权值+1,求最长不下降子序列最长能为多少

其实我根本没想到可以用DP做

f[i][j]表示前i棵,操作j次,最长子序列长度

p[x][y]表示操作x次后,最高玉米为y时的最长子序列长度

那么以n棵玉米分阶段,对于每个阶段

f[i][j]=max{p[k][l]}+1,  其中k=1 to j , l=1 to a[i]+j

然后用树状数组维护p[][]的最大值

 

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 using namespace std;
 5 int p[505][6005],f[10005][505];
 6 int n,K,M,ans,a[10005];
 7 
 8 int solve(int x, int t){
 9     int res=0;
10     while (x){
11         int y=t;
12         while (y){
13             res=max(res,p[x][y]);
14             y-=y&-y;
15         }
16         x-=x&-x;
17     }
18     return res;
19 }
20 
21 void update(int x, int t, int c){
22     while (x<=K){
23         int y=t;
24         while (y<=M){
25             p[x][y]=max(p[x][y],c);
26             y+=y&-y;
27         }
28         x+=x&-x;
29     }
30 }
31 
32 int main(){
33     scanf("%d%d", &n, &K);
34     K++;
35     for (int i=1; i<=n; i++){
36         scanf("%d", &a[i]);
37         M=max(M,a[i]);
38     }
39     M+=K;
40     ans=0;
41     for (int i=1; i<=n; i++){
42         for (int j=1; j<=K; j++){
43             f[i][j]=solve(j,a[i]+j)+1;  // k=1~j; l=a[i]~a[i]+j;  p[k][l]用了k次,最高是a[i]+j 最长子序列长度 
44             ans=max(ans,f[i][j]);
45         }
46         for (int j=1; j<=K; j++)
47             update(j,a[i]+j,f[i][j]);
48     }
49     printf("%d\n", ans);
50     return 0;
51 }

 

posted @ 2016-05-26 20:56  mzl0707  阅读(238)  评论(0编辑  收藏  举报