[题目链接]
https://www.lydsy.com/JudgeOnline/problem.php?id=3594
[算法]
首先有一个结论 : 每次选择的区间右端点一定是n
根据这个结论 , 设fi,j表示前i株玉米拔高j次的最长不下降子序列长度
则fi,j = max{fp,q + 1} (q <= j , ap + q <= ai + j)
二维树状数组优化即可
时间复杂度 : O(NKlogK ^ 2)
[代码]
#include<bits/stdc++.h> using namespace std; #define N 10010 #define K 510 #define M 5510 typedef long long ll; typedef long double ld; typedef unsigned long long ull; #define rint register int int n , k , m; int a[N]; int c[K][M]; template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); } template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); } template <typename T> inline void read(T &x) { T f = 1; x = 0; char c = getchar(); for (; !isdigit(c); c = getchar()) if (c == ‘-‘) f = -f; for (; isdigit(c); c = getchar()) x = (x << 3) + (x << 1) + c - ‘0‘; x *= f; } inline int lowbit(int x) { return x & (-x); } inline void modify(int x , int y , int value) { for (rint i = x; i <= k + 1; i += lowbit(i)) { for (rint j = y; j <= m; j += lowbit(j)) { chkmax(c[i][j] , value); } } } inline int query(int x , int y) { int ret = 0; for (rint i = x; i; i -= lowbit(i)) { for (rint j = y; j; j -= lowbit(j)) { chkmax(ret , c[i][j]); } } return ret; } int main() { // f(i , j) = max{ f(p , q) + 1 } ( q <= j , ap + q <= ai + j } read(n); read(k); int mx = 0; for (rint i = 1; i <= n; i++) { read(a[i]); chkmax(mx , a[i]); } m = k + mx + 1; int ans = 0; for (rint i = 1; i <= n; i++) { for (rint j = k; ~j; j--) { int tmp = query(j + 1 , a[i] + j) + 1; chkmax(ans , tmp); modify(j + 1 , a[i] + j , tmp); } } printf("%d\n" , ans); return 0; }
原文地址:https://www.cnblogs.com/evenbao/p/10360374.html
时间: 2024-10-30 01:31:48