文章目录

‹
›

T2 最长上升子序列(lis)题解

T2 最长上升子序列(lis)题解

题目大意

给定 \(1 \sim n\) 的排列 \(a\)。对每个 \(i = 1, 2, \dots, n-1\),交换 \(a_i\) 与 \(a_{i+1}\),求交换后的最长严格上升子序列(LIS)长度。各次交换相互独立,每次都从原排列开始。

思路

核心观察:相邻交换后,LIS 长度只能是 \(L-1\)、\(L\) 或 \(L+1\)(\(L\) 为原 LIS 长度)。因为交换只影响同时包含这两个元素的子序列,删去其中一个就能恢复原排列的子序列。

分两种情况讨论:

情况一:\(a_i < a_{i+1}\)(递增对)

交换后不会产生新的上升子序列,只会破坏同时选择这两个元素的原子序列。

  • 如果两个位置都是必经位置(每条 LIS 都必须经过它们),那么所有原 LIS 都被破坏,答案为 \(L-1\)
  • 否则,存在一条 LIS 不包含其中至少一个元素,这条 LIS 保留,答案仍为 \(L\)

情况二:\(a_i > a_{i+1}\)(递减对)

原 LIS 全部保留,答案不会减少。新增的上升子序列必须同时选择交换后的两个元素(\(y = a_{i+1}\) 在前,\(x = a_i\) 在后)。

设 \(f_i\) 为以 \(i\) 结尾的 LIS 长度,\(g_i\) 为以 \(i\) 开头的 LIS 长度,则:

\(ans_i = \max(L,\ f_{i+1} + g_i)\)

左侧选值 \(< y\) 的最长上升链(即 \(f_{i+1}\)),右侧选值 \(> x\) 的最长上升链(即 \(g_i\)),两部分可以直接拼接。

必经位置的判定

位置 \(i\) 属于某条 LIS 的充要条件:\(f_i + g_i - 1 = L\)。

按 \(f_i\) 分层,记第 \(k\) 层有多少个这样的候选。必经位置满足:

  • \(f_i + g_i - 1 = L\)(在某条 LIS 上)
  • 且 \(cnt[f_i] = 1\)(这一层只有它一个候选,每条 LIS 都必须选它)

AC code

#include <bits/stdc++.h>
using namespace std;

using ll = long long;

const int N = 200000 + 5;

int n;
int a[N], f[N], g[N];
int stk[N], top;
int cnt[N];

bool necessary[N];
int ans[N];

int main () {
	freopen("lis.in", "r", stdin);
	freopen("lis.out", "w", stdout);
	ios::sync_with_stdio (false);
	cin.tie (0);

	cin >> n;

	for (int i = 1; i <= n; i ++) cin >> a[i];

	top = 0;

	for (int i = 1; i <= n; i ++) {
		int k = lower_bound (stk + 1, stk + top + 1, a[i]) - stk;
		stk[k] = a[i];

		if (k > top) top = k;

		f[i] = k;
	}

	int L = top;

	top = 0;

	for (int i = n; i >= 1; i --) {
		int v = n + 1 - a[i];
		int k = lower_bound (stk + 1, stk + top + 1, v) - stk;
		stk[k] = v;

		if (k > top) top = k;

		g[i] = k;
	}

	for (int i = 1; i <= n; i ++)
		if (f[i] + g[i] - 1 == L) 
			cnt[f[i]] ++;

	for (int i = 1; i <= n; i ++)
		necessary[i] = (f[i] + g[i] - 1 == L && cnt[f[i]] == 1);

	for (int i = 1; i < n; i ++) {
		if (a[i] < a[i + 1]) ans[i] = L - (necessary[i] && necessary[i + 1]);
		else ans[i] = max (L, f[i + 1] + g[i]);
	}

	for (int i = 1; i < n; i ++) cout << ans[i] << ' ';

	return 0;
}
posted @ 2026-10-02 20:03  lvwangshu  阅读(16)  评论(0)    收藏  举报