SCOI2015 方伯伯的玉米田
方伯伯的玉米田
方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美。这排玉米一共有 \(N\) 株,它们的高度参差不齐。
方伯伯认为单调不下降序列很美,所以他决定先把一些玉米拔高,再把破坏美感的玉米拔除掉,使得剩下的玉米的高度构成一个单调不下降序列。方伯伯可以选择一个区间,把这个区间的玉米全部拔高 \(1\) 单位高度,他可以进行最多 \(K\) 次这样的操作。拔玉米则可以随意选择一个集合的玉米拔掉。
问能最多剩多少株玉米,来构成一排美丽的玉米。
对于所有数据,\(1 < N < 10000,\ 1 < K \leq 500,\ 1 \leq a_i \leq 5000\)。
题解
https://www.cnblogs.com/forth/p/9318506.html
https://blog.csdn.net/Bill_Benation/article/details/87184405
首先,通过思考我们可以得出每次操作区间的右端点一定为\(n\),否则后面玉米的高度相对前面的高度就会减少,被拔的也就会变多,不满足最优。
由此,我们可以设\(f(i,j)\)表示以第\(i\)个玉米为结尾,且第\(i\)个玉米被拔高了\(j\)次的最长非降子序列长度。
考虑用数据结构维护这个转移。\(x< i\)显然不用管,\(a_x+y\leq a_i+j\)和\(y\leq j\)可以用二维树状数组维护。具体而言,我们可以把\(f(x,y)\)存到二维树状数组里的\(g(a_x+y,y)\),然后对\(f(i,j)\)查询\(g(a_i+j,j)\)就行了。
时间复杂度\(O(nK\log(a_iK))\)。
int n,K,mx;
int a[10010],s[5510][510];
#define lowbit(x) (x&-x)
void insert(int x,int y,int v){
for(int i=x;i<=mx+K;i+=lowbit(i))
for(int j=y+1;j<=K+1;j+=lowbit(j))
s[i][j]=max(s[i][j],v);
}
int query(int x,int y){
int ans=0;
for(int i=x;i;i-=lowbit(i))
for(int j=y+1;j;j-=lowbit(j))
ans=max(ans,s[i][j]);
return ans;
}
#undef lowbit
int main(){
read(n),read(K);
for(int i=1;i<=n;++i) read(a[i]);
mx=*max_element(a+1,a+n+1);
for(int i=1;i<=n;++i)for(int j=K;j>=0;--j)
insert(a[i]+j,j,query(a[i]+j,j)+1);
printf("%d\n",query(mx+K,K));
return 0;
}