方伯伯的玉米田
方伯伯在自己的农田边散步,他突然发现田里的一排玉米非常的不美。这排玉米一共有 (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)次的最长非降子序列长度。
[f(i,j)=max_{x< i,yleq j}{f(x,y)+1mid a_x+yleq a_i+j}
]
考虑用数据结构维护这个转移。(x< i)显然不用管,(a_x+yleq a_i+j)和(yleq j)可以用二维树状数组维护。具体而言,我们可以把(f(x,y))存到二维树状数组里的(g(a_x+y,y)),然后对(f(i,j))查询(g(a_i+j,j))就行了。
时间复杂度(O(nKlog(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
",query(mx+K,K));
return 0;
}