动态规划+数据结构优化
每次操作区间的右端点一定为n,因为要尽量的让后面的数更大
记 f[i][k] 为以第i个玉米为结尾一共操作了k次的最长不下降序列的长度
因为每次操作右端点为n,左端点小于等于i
所以此时i的高度为 h[i] + k
则 f[i][k] = max(f[j][l]) + 1 // h[j] + l <= h[i] + k, j < i, l <= k
将每个状态 f[i][k] 可以表示为 (k, h[i] + k) // 操作次数,结尾高度
每次转移相当于取 (K, H) K <= k, H <= h[i] + k的最大值
可以用二维树状数组来维护
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int N = 1e4 + 5, K = 505, H = 6005; 5 6 int n, k, h[N], Max, f[N][K], tr[K][H], ans; 7 8 int query(int x, int y) { 9 int i = x, res = 0; 10 while (i) { 11 int j = y; 12 while (j) { 13 res = max(res, tr[i][j]); 14 j -= (j & (-j)); 15 } 16 i -= (i & (-i)); 17 } 18 return res; 19 } 20 21 void update(int x, int y, int val) { 22 int i = x; 23 while (i <= k + 1) { 24 int j = y; 25 while (j <= Max) { 26 tr[i][j] = max(tr[i][j], val); 27 j += (j & (-j)); 28 } 29 i += (i & (-i)); 30 } 31 return; 32 } 33 34 int main() { 35 cin >> n >> k; 36 for (int i = 1; i <= n; i++) { 37 scanf("%d", &h[i]); 38 Max = max(Max, h[i] + k); 39 } 40 for (int i = 1; i <= n; i++) 41 for (int j = k; j >= 0; j--) { 42 f[i][j] = query(j + 1, h[i] + j) + 1; 43 ans = max(ans, f[i][j]); 44 update(j + 1, h[i] + j, f[i][j]); 45 } 46 cout << ans << endl; 47 }
原文地址:https://www.cnblogs.com/ympc2005/p/12318290.html
时间: 2024-11-12 19:44:17