SP57 SUPPER - Supernumbers in a permutation
考虑 dp 求出 \(f_i\) 表示以 \(i\) 结尾的最长上升子序列长度,\(g_i\) 表示以 \(i\) 开头的最长上升子序列长度。
有转移:
\[f_i=\max\limits_{1\le j<i\,\land\,a_j<a_i}f_j+1
\]
\[g_i=\max\limits_{i<j\le n\,\land\,a_i<a_j}g_j+1
\]
考虑经过一个位置 \(i\) 在最长上升子序列上,一定是以它往后最长的一个最长上升子序列,接在它之前的 \(j\) 位置后,然后从 \(j\) 位置往前延申一段最长上升子序列。
形式化地,经过一个位置 \(i\) 的最长上升子序列长度为:
\[g_i+\max\limits_{1\le j<i\,\land\,a_j<a_i}f_j
\]
求出这个东西,看是否等于原序列的最长上升子序列。
考虑用扫描线解决下标的限制,线段树维护值域的限制,单组数据时间复杂度为 \(\mathcal{O}(n\log n)\),空间复杂度为 \(\mathcal{O}(n)\)。
#include <bits/stdc++.h>
#define ls(x) ((x) << 1)
#define rs(x) (((x) << 1) | 1)
using namespace std; const int N = 1e5 + 1;
int n, a[N], f[N], g[N], ans; vector<int> tmp;
struct SegmentTree {
int mx[N << 2];
void build(int x, int l, int r) {
mx[x] = 0; if (l == r) return; int mid = (l + r) >> 1;
build(ls(x), l, mid); build(rs(x), mid + 1, r);
}
void modify(int x, int l, int r, int k, int v) {
if (l == r) return void(mx[x] = v); int mid = (l + r) >> 1;
if (k <= mid) modify(ls(x), l, mid, k, v);
else modify(rs(x), mid + 1, r, k, v); mx[x] = max(mx[ls(x)], mx[rs(x)]);
}
int query(int x, int l, int r, int ql, int qr) {
if (ql > qr) return 0; if (ql <= l && r <= qr) return mx[x];
int mid = (l + r) >> 1, ret = 0;
if (ql <= mid) ret = query(ls(x), l, mid, ql, qr);
if (qr > mid) ret = max(ret, query(rs(x), mid + 1, r, ql, qr)); return ret;
}
} SGT;
signed main() {
cin.tie(0), cout.tie(0), ios::sync_with_stdio(0);
while (cin >> n) {
for (int i = 1; i <= n; ++i) cin >> a[i]; SGT.build(1, 1, n); ans = 0;
for (int i = 1; i <= n; ++i) {
f[i] = SGT.query(1, 1, n, 1, a[i] - 1) + 1;
SGT.modify(1, 1, n, a[i], f[i]); ans = max(ans, f[i]);
}
SGT.build(1, 1, n); tmp.clear();
for (int i = n; i >= 1; --i) {
g[i] = SGT.query(1, 1, n, a[i] + 1, n) + 1;
SGT.modify(1, 1, n, a[i], g[i]);
}
SGT.build(1, 1, n);
for (int i = 1; i <= n; ++i) {
if (SGT.query(1, 1, n, 1, a[i] - 1) + g[i] == ans)
tmp.emplace_back(a[i]);
SGT.modify(1, 1, n, a[i], f[i]);
}
cout << tmp.size() << '\n'; stable_sort(tmp.begin(), tmp.end());
for (int i : tmp) cout << i << ' '; cout << '\n';
}
return 0;
}

浙公网安备 33010602011771号