[BZOJ4993||4990] [Usaco2017 Feb]Why Did the Cow Cross the Road II(DP + 线段树)
f[i][j]表示当前第i个,且最后一个位置连接到j
第一维可以省去,能连边的点可以预处理出来,dp可以用线段树优化
#include <cstdio> #include <iostream> #include <algorithm> #define N 100001 #define root 1, 1, n #define ls now << 1, l, mid #define rs now << 1 | 1, mid + 1, r using namespace std; int n, ans, cnt; int a[N], pos[N], sum[N << 2], f[N]; inline int read() { int x = 0, f = 1; char ch = getchar(); for(; !isdigit(ch); ch = getchar()) if(ch == '-') f = -1; for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - '0'; return x * f; } inline int query(int now, int l, int r, int x, int y) { if(x > y) return 0; if(x <= l && r <= y) return sum[now]; int mid = (l + r) >> 1, ret = 0; if(x <= mid) ret = max(ret, query(ls, x, y)); if(mid < y) ret = max(ret, query(rs, x, y)); return ret; } inline void update(int now, int l, int r, int x, int d) { if(l == r) { sum[now] = max(sum[now], d); return; } int mid = (l + r) >> 1; if(x <= mid) update(ls, x, d); else update(rs, x, d); sum[now] = max(sum[now << 1], sum[now << 1 | 1]); } int main() { int i, j, x; n = read(); for(i = 1; i <= n; i++) x = read(), pos[x] = i; for(i = 1; i <= n; i++) { cnt = 0; x = read(); for(j = max(1, x - 4); j <= min(n, x + 4); j++) a[++cnt] = pos[j]; sort(a + 1, a + cnt + 1); for(j = cnt; j >= 1; j--) { x = query(root, 1, a[j] - 1) + 1; f[a[j]] = max(f[a[j]], x); update(root, a[j], x); } } for(i = 1; i <= n; i++) ans = max(ans, f[i]); printf("%d\n", ans); return 0; }