SPOJ LIS2 - Another Longest Increasing Subsequence Problem(CDQ分治优化DP)
题目链接 LIS2
经典的三维偏序问题。
考虑$cdq$分治。
不过这题的顺序应该是
$cdq(l, mid)$
$solve(l, r)$
$cdq(mid+1, r)$
因为有个$DP$。
#include <bits/stdc++.h> using namespace std; #define rep(i, a, b) for (int i(a); i <= (b); ++i) #define dec(i, a, b) for (int i(a); i >= (b); --i) #define MP make_pair #define fi first #define se second typedef long long LL; const int N = 1e5 + 10; struct node{ int x, y, z; int num; void scan() { scanf("%d%d", &y, &z);} void print() { printf("%d %d %d\n", x, y, z);} friend bool operator < (const node &a, const node &b){ return a.y == b.y ? a.z < b.z : a.y < b.y; } } p[N], q[N]; int a[N], b[N]; int n; int cnt; int c[N]; int ans; void update(int x, int val){ for (; x <= n; x += x & -x) c[x] = max(c[x], val); } int query(int x){ int ret = 0; for (; x ; x -= x & -x) ret = max(ret, c[x]); return ret; } void recover(int x){ for (; x <= n; x += x & -x) c[x] = 0; } bool cmp(const node &a, const node &b){ return a.x < b.x; } void cdq(int l, int r){ if (l == r) return; int mid = (l + r) >> 1; cdq(l, mid); sort(p + l, p + mid + 1); sort(p + mid + 1, p + r + 1); int j = l; for (int i = mid + 1; i <= r; ++i){ for (; j <= mid && p[j].y < p[i].y; ++j){ update(p[j].z, p[j].num); } p[i].num = max(p[i].num, query(p[i].z - 1) + 1); } rep(i, l, mid) recover(p[i].z); sort(p + mid + 1, p + r + 1, cmp); cdq(mid + 1, r); } int main(){ scanf("%d", &n); rep(i, 1, n) p[i].scan(); rep(i, 1, n) a[i] = p[i].y; rep(i, 1, n) p[i].num = 1; sort(a + 1, a + n + 1); cnt = unique(a + 1, a + n + 1) - a - 1; rep(i, 1, n) p[i].y = lower_bound(a + 1, a + cnt + 1, p[i].y) - a; rep(i, 1, n) a[i] = p[i].z; sort(a + 1, a + n + 1); cnt = unique(a + 1, a + n + 1) - a - 1; rep(i, 1, n) p[i].z = lower_bound(a + 1, a + cnt + 1, p[i].z) - a; rep(i, 1, n) p[i].x = i; cdq(1, n); ans = 0; rep(i, 1, n) ans = max(ans, p[i].num); printf("%d\n", ans); return 0; }