bzoj 3594: [Scoi2014]方伯伯的玉米田
3594: [Scoi2014]方伯伯的玉米田
Time Limit: 60 Sec Memory Limit: 128 MB
Submit: 1399 Solved: 627
[Submit][Status][Discuss]
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
从贪心的角度,显然有从i到n整体提高要比i到某个r提高优。因为当提高范围为r(r!=n)时,无非两种情况一种是在[r+1,n]存在一个庄稼原来比(I,r]中的某一个使得在r以前长度最大值的点大于或等于,另一种是没有更大的。那么对于第二种对于答案没有贡献,我们从i到n拔高也就没影响,而当出现第一种时,可能由于多次拔高使得原本可以在[r+1,n]之间可以有贡献的点失败了,那么显然没有从i到n拔高更优。
不优化的姿势呢显然。
F[i][j]表示第i个位置时(必须使用第i个位置)使用了j次技能的最大长度。所以F[i][j]=max(F[x][y])(x<i,y<j,a[x]<=a[i]+y-j) ===>(x<i,y<j,a[x]+y<=a[i]+j)。显然对于每次添加,都是现在已有状态都是满足x<i。现在我们可以将y与a[x]+y搞成树状数组,每次添加都是在左下角矩形中选一个最大值。然后这两维就可以优化为log2(n)*log2(m+max(a[i]));
总时间复杂度就是O(n*k* log2(n)*log2(m+max(a[i])))。恩,反正过了=-=。
1 #include<cstdio> 2 #include<iostream> 3 #define lowbit(x) (x&(-x)) 4 using namespace std; 5 const int N=10050; 6 int n,m,mx; 7 int a[N]; 8 int c[N][550]; 9 void add(int x,int y,int w){ 10 for(int i=x;i<=mx;i+=lowbit(i)) 11 for(int j=y;j<=m+1;j+=lowbit(j)) 12 c[i][j]=max(w,c[i][j]); 13 } 14 inline int sum(int x,int y){ 15 int ans=0; 16 for(int i=x;i;i-=lowbit(i)) 17 for(int j=y;j;j-=lowbit(j)) 18 ans=max(ans,c[i][j]); 19 return ans; 20 } 21 int f[N][550]; 22 int main(){ 23 scanf("%d%d",&n,&m); 24 for(int i=1;i<=n;i++){scanf("%d",a+i);mx=a[i]>mx?a[i]:mx;} 25 mx+=m; 26 int ans=0; 27 for(int i=1;i<=n;i++){ 28 for(int j=m;j>=0;j--){ 29 f[i][j]=sum(a[i]+j,j+1)+1; 30 // printf("f[%d][%d]=%d\n",i,j,f[i][j]); 31 add(a[i]+j,j+1,f[i][j]); 32 ans=max(ans,f[i][j]); 33 } 34 } 35 printf("%d",ans); 36 } 37 /* 38 3 1 39 2 1 3 40 */