【c++题解】经典题目:带修改的 LIS 问题——CF650D Zip-line
CF650D Zip-line
题意
带修改的 LIS 问题:给你一个长为 nnn 的序列,mmm 个询问,每次询问把位置 xxx 的值修改为 yyy 后的 LIS,询问间相互独立。
题解
代码:
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;inline void chkmax(int &x, int y) {if (y > x) x = y;
}
inline void chkmin(int &x, int y) {if (y < x) x = y;
}const int N = 8e5 + 10;int n, m, a[N];
int btot, b[N];vector<pair<int, int>> qq[N];
int lans, vis[N], ans[N], F[N], G[N];int f[N], g[N], is[N];struct BIT {int len, mx[N];void init(int _l) {len = _l;for (int i = 0; i <= len; ++i) mx[i] = 0;}void chkmx(int x, int v) {for (; x <= len; x += x & -x) chkmax(mx[x], v);}int qry(int x) {int res = 0;for (; x; x -= x & -x) chkmax(res, mx[x]);return res;}
} t;void init() {t.init(btot);for (int i = 1; i <= n; ++i) f[i] = t.qry(a[i] - 1) + 1, t.chkmx(a[i], f[i]);t.init(btot);for (int i = n; i >= 1; --i)g[i] = t.qry(btot - a[i]) + 1, t.chkmx(btot - a[i] + 1, g[i]);for (int i = 1; i <= n; ++i) chkmax(lans, f[i] + g[i] - 1);for (int i = 1; i <= n; ++i)if (f[i] + g[i] - 1 == lans) ++vis[f[i]];for (int i = 1; i <= n; ++i)if (f[i] + g[i] - 1 == lans && vis[f[i]] == 1) is[i] = 1;
}int main() {ios::sync_with_stdio(false), cin.tie(nullptr);cin >> n >> m;for (int i = 1; i <= n; ++i) cin >> a[i], b[++btot] = a[i];for (int i = 1, x, v; i <= m; ++i) {cin >> x >> v, qq[x].push_back(make_pair(v, i));b[++btot] = v;}sort(b + 1, b + btot + 1);btot = unique(b + 1, b + btot + 1) - b - 1;auto Get = [&](int x) -> int {return lower_bound(b + 1, b + btot + 1, x) - b;};for (int i = 1; i <= n; ++i) a[i] = Get(a[i]);for (int i = 1; i <= n; ++i)for (pair<int, int> &it : qq[i])it.first = Get(it.first);init();for (int i = 1; i <= n; ++i) {for (pair<int, int> it : qq[i])if (is[i]) ans[it.second] = lans - 1;else ans[it.second] = lans;}t.init(btot);for (int i = 1; i <= n; ++i) {for (pair<int, int> it : qq[i])F[it.second] = t.qry(it.first - 1) + 1;t.chkmx(a[i], f[i]);}t.init(btot);for (int i = n; i >= 1; --i) {for (pair<int, int> it : qq[i]) G[it.second] = t.qry(btot - it.first) + 1;t.chkmx(btot - a[i] + 1, g[i]);}for (int i = 1; i <= m; ++i) cout << max(ans[i], F[i] + G[i] - 1) << '\n';return 0;
}