Address
https://www.lydsy.com/JudgeOnline/problem.php?id=4553
Solution
下面设三个值:
:原序列
位置的值。
:
位置可能被变换成的最小数值。
:
位置可能被变换成的最大数值。
而一个合法的子序列必须满足,对于相邻的两个位置
:
(1)即使
位置被变换成最小值也必须要满足单调不降的性质。
即:
(2)即使 位置被变换成最大值也必须要满足单调不降的性质。
即:
所以就有一个 dp 模型了!
表示以 为结尾的最长子序列。
转移显然:
会发现这特别像 BZOJ 2253 纸箱堆叠(二维上升子序列)。
用二维线段树 / CDQ 分治优化,复杂度 。
Code
发现 BZOJ 的空间限制不让二维线段树通过
#include <cmath>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define For(i, a, b) for (i = a; i <= b; i++)
using namespace std;
inline int read() {
int res = 0; bool bo = 0; char c;
while (((c = getchar()) < '0' || c > '9') && c != '-');
if (c == '-') bo = 1; else res = c - 48;
while ((c = getchar()) >= '0' && c <= '9')
res = (res << 3) + (res << 1) + (c - 48);
return bo ? ~res + 1 : res;
}
const int N = 1e5 + 5;
int n, m, a[N], _min[N], _max[N], T[N], ans;
struct cyx {
int _min, x, _max, id, res;
} q[N];
inline bool comp1(const cyx &a, const cyx &b) {
return a.x < b.x || (a.x == b.x && a._max < b._max);
}
inline bool comp2(const cyx &a, const cyx &b) {
return a._min < b._min || (a._min == b._min && a.x < b.x);
}
inline bool comp3(const cyx &a, const cyx &b) {
return a.id < b.id;
}
void clean(int x) {
for (; x <= 100000; x += x & -x)
T[x] = 0;
}
void change(int x, int v) {
for (; x <= 100000; x += x & -x)
T[x] = max(T[x], v);
}
int ask(int x) {
int res = 0;
for (; x; x -= x & -x)
res = max(res, T[x]);
return res;
}
void zzqsolve(int l, int r) {
if (l == r) return (void) (ans = max(ans, q[l].res));
int i, p = l, mid = l + r >> 1;
zzqsolve(l, mid);
sort(q + l, q + mid + 1, comp1);
sort(q + mid + 1, q + r + 1, comp2);
For (i, mid + 1, r) {
while (p <= mid && q[p].x <= q[i]._min)
change(q[p]._max, q[p].res), p++;
q[i].res = max(q[i].res, ask(q[i].x) + 1);
}
For (i, l, mid) clean(q[i]._max);
sort(q + mid + 1, q + r + 1, comp3);
zzqsolve(mid + 1, r);
}
int main() {
int i, x, y;
n = read(); m = read();
For (i, 1, n) a[i] = _min[i] = _max[i] = read();
while (m--) {
x = read(); y = read();
_min[x] = min(_min[x], y);
_max[x] = max(_max[x], y);
}
For (i, 1, n) q[i] = (cyx) {_min[i], a[i], _max[i], i, 1};
zzqsolve(1, n);
cout << ans << endl;
return 0;
}