洛谷 P3287
不难发现一定是拔高一段后缀。
所以设 fi,j 表示考虑前 i 个位置,拔高 j 次,第 i 个位置强制选的 LIS 的长度。
则有 fi,j=max1≤x<i,0≤y≤j,ax+y≤ai+j{fx,y+1}。
x<i 天然满足,而剩下两个条件可以用二维 BIT 优化。
因为 j 可以为 0 所以要整体右移一位。
而且不难发现为了不让同一个 i 之间转移所以像背包一样 j 倒序枚举。
时间复杂度 O(nklogklogw),只能说非常离谱。
Code:
#include <bits/stdc++.h>
using namespace std;
const int N = 10005, M = 5005, K = 505;
void chkmax(int &a, int b) { if (a < b) a = b; }
int n, m;
int a[N], f[N][K], c[K][K+M];
void upd(int x, int y, int v) {
for (int i = x; i <= m + 1; i += i & -i)
for (int j = y; j <= 5500; j += j & -j) chkmax(c[i][j], v);
}
int query(int x, int y) {
int res = 0;
for (int i = x; i; i -= i & -i)
for (int j = y; j; j -= j & -j) chkmax(res, c[i][j]);
return res;
}
int main() {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; ++i) scanf("%d", &a[i]);
for (int i = 1; i <= n; ++i)
for (int j = m; ~j; --j)
upd(j + 1, a[i] + j, f[i][j] = query(j + 1, a[i] + j) + 1);
printf("%d", query(m + 1, 5500));
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本