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 }