CF946G

首先将所有 aiaii

fi,0/1 表示前 i 个数字,强制选第 i 个数,未删过数字/已经删过数字的最长不下降子序列的长度。

则有 fi,0=maxajai{fj,0}+1fi,1=maxajai{fj,1}+1.

对于去掉一个元素的情况,发现后面所有点的下标都会减去 1,因此 fi,1=maxajai+1,j<i1{fj,0}+1

将所有涉及到的值离散化后用树状数组维护即可。

具体细节看代码。

Code:

#include <bits/stdc++.h>
using namespace std;
const int N = 200005, M = 400005;
int n;
int a[N], b[N], _[M], tot;
int c[M][3];
int f[N][2];

void upd(int x, int y, int k) { for (; x <= tot; x += x & -x) c[x][k] = max(c[x][k], y); }
int query(int x, int k) { int res = 0; for (; x; x -= x & -x) res = max(res, c[x][k]); return res; }

int main() {
	scanf("%d", &n);
	for (int i = 1; i <= n; ++i) scanf("%d", &a[i]), a[i] -= i, b[i] = a[i] + 1, _[++tot] = a[i], _[++tot] = b[i];
	sort(_ + 1, _ + tot + 1), tot = unique(_ + 1, _ + tot + 1) - (_ + 1);
	for (int i = 1; i <= n; ++i) a[i] = lower_bound(_ + 1, _ + tot + 1, a[i]) - _, b[i] = lower_bound(_ + 1, _ + tot + 1, b[i]) - _;
	int ans = 0;
	for (int i = 1; i <= n; ++i) {
		int val1 = query(a[i], 0), val2 = query(a[i], 1), val3 = query(b[i], 2);
		f[i][0] = val1 + 1, f[i][1] = val2 + 1; if (i > 2) f[i][1] = max(f[i][1], val3 + 1);
		upd(a[i], f[i][0], 0), upd(a[i], f[i][1], 1); if (i > 1) upd(a[i - 1], f[i - 1][0], 2);
		ans = max(ans, max(f[i][0], f[i][1]));
	}
	printf("%d", max(0, n - 1 - ans));
	return 0;
}
posted @   Kobe303  阅读(22)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列01:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现
· 25岁的心里话
点击右上角即可分享
微信分享提示