zzh学长留的毒瘤题......
首先这题先明白一个性质:
当我们选择增区间的高度时,我们应该将所选的增加的左端点到n全增大,因为我们要求
最后成的单调不下降序列长度最大,所以这样增稳赚不亏。。。。
然后那么我们发现这题最后的点的最优高度是a[n]+K确定的
设数组含义f[j][k]表示当前玉米高度j,k次操作的最长序列长度
并且我们可以把此题看作三位偏序:
1. 当前玉米位置i,由1-i-1转移
2. 当前玉米高度j,由1-j转移
3.当前玉米已操作k,由1-k-1转移
用树状数组维护j,k,(很显然了.....)
(为了节省内存所以我们第一位循环是i,这样保证我们的i是有序的,就不需要写在数组里,
其实i,j,k,任选两位都行,只是为了省内存嘛.......)
注意点:
1.循环k时倒序,(显然嘛.....当前的k若是正序,他的插入会影响当前位k的枚举)
2.预处理要注意,根据你的枚举来定,当然也可以不
3.ans值不一定选中最后一个点
1 #include<map> 2 #include<iostream> 3 #include<cstdio> 4 #include<cstring> 5 #include<algorithm> 6 #include<cmath> 7 #include<string> 8 #include<vector> 9 #define int long long 10 using namespace std; 11 int c[511][5501]; 12 int a[11001]; 13 int maxn; 14 int lowbit(int x){return x&(-x);} 15 int n,K; 16 void add(int x,int y,int sum)//x 第几个操作 y 高度 k第k操作 17 { 18 for(int i=x;i<=K+1;i+=lowbit(i)) 19 { 20 for(int j=y;j<=maxn+K;j+=lowbit(j)) 21 { 22 c[i][j]=max(c[i][j],sum); 23 } 24 } 25 } 26 int query(int x,int y) 27 { 28 int ans=0; 29 for(int i=x;i>=1;i-=lowbit(i)) 30 { 31 for(int j=y;j>=1;j-=lowbit(j)) 32 { 33 ans=max(ans,c[i][j]); 34 } 35 } 36 return ans; 37 } 38 int ans=0; 39 signed main() 40 { 41 scanf("%lld%lld",&n,&K); 42 for(int i=1;i<=n;++i) 43 { 44 scanf("%lld",&a[i]); 45 maxn=max(a[i],maxn); 46 } 47 for(int i=1;i<=n;++i) 48 { 49 for(int j=K;j>=0;--j) 50 { 51 int th=query(j+1,a[i]+j)+1; 52 //printf("dp[%lld][%lld]=%lld ",j,a[i]+j); 53 ans=max(th,ans); 54 add(j+1,a[i]+j,th); 55 } 56 } 57 //int ans=query(K+1,a[n]+K); 58 printf("%lld ",ans); 59 }