【题解】洛谷P3287:方伯伯的玉米田

P3287 [SCOI2014] 方伯伯的玉米田

感觉其实也不难。

我们必然知道选择加区间的右端点是 \(n\),因为如果只选中间的话会与后面相差开,不如直接选上右,因为有两个变量,位置与操作次数,所有我们就设状态为 \(f_{x,k}\) 为我们 \(x\) 为左端点被加 \(k\) 次的最长不下降子序列,此时我们的树状数组也要开两维同样记录,查找时也两维查找。

#include <bits/stdc++.h>
#define int long long
#define ls p<<1
#define rs p<<1|1 
#define re register 
const int N=1e4+10;
const int mod=1e9+7;
using namespace std;
int n,k;
int a[N];
int f[N][505];
int t[N][505];

int lb(int x){
	return x&-x;
}
void change(int x,int y,int z){
	for(int i=x;i<=5500;i+=lb(i)){
		for(int j=y;j<=k+1;j+=lb(j)){
			t[i][j]=max(t[i][j],z);
		}
	}
}
int query(int x,int y){
	int ans=0;
	for(int i=x;i;i-=lb(i)){
		for(int j=y;j;j-=lb(j)){
			ans=max(ans,t[i][j]);
		}
	}
	return ans;
}
signed main(){
    ios::sync_with_stdio(false);
    cin.tie(nullptr);
	cin>>n>>k;
	for(int i=1;i<=n;i++){
		cin>>a[i];
	}
	for(int i=1;i<=n;i++){
		for(int j=k;j>=0;j--){
			f[i][j]=query(a[i]+j,j+1)+1;
			change(a[i]+j,j+1,f[i][j]);
		} 
	}
	cout<<query(5500,k+1);
	return 0; 
}
posted @ 2024-11-11 18:49  sad_lin  阅读(0)  评论(0编辑  收藏  举报