[USACO17FEB] Why Did the Cow Cross the Road II P [树状数组优化dp]

mac2024-01-28  33

W h y   D i d   t h e   C o w   C r o s s   t h e   R o a d Why\ Did\ the\ Cow\ Cross\ the\ Road Why Did the Cow Cross the Road

题目描述见链接 .


正 解 部 分 \color{red}{正解部分}

F [ i , j ] F[i, j] F[i,j] 表示 A A A 序列前 i i i 项, B B B 序列前 j j j 项 的最大匹配数,

i , j i,j i,j 不相连: F [ i , j ] = max ⁡ ( F [ i − 1 , j ] , F [ i , j − 1 ] ) F[i, j] = \max(F[i-1,j],F[i,j-1]) F[i,j]=max(F[i1,j],F[i,j1]) i , j i, j i,j 相连: F [ i , j ] = max ⁡ ( F [ i − 1 , j − 1 ] + 1 ) F[i, j] = \max(F[i-1,j-1]+1) F[i,j]=max(F[i1,j1]+1)

经典的最长公共子序列算法 .

考虑优化, 发现 i i i j j j 相连当且仅当 ∣ A i − B j ∣ ≤ 4 |A_i-B_j| \le 4 AiBj4, 于是在 i i i 确定的情况下, j j j 最多只有 9 9 9 个可能的取值,

所以可以记下 B j B_j Bj 的位置 p o s B j pos_{B_j} posBj 从小到大枚举 i i i, 再枚举 9 9 9 种可能的 B j B_j Bj, 从 F [ i − 1 , 0   . . .   p o s B j − 1 − 1 ] + 1 F[i-1, 0 \ ...\ pos_{B_j-1}-1]+1 F[i1,0 ... posBj11]+1 转移过来, 使用 树状数组 优化 最大前缀 即可实现 O ( 9 × N log ⁡ N ) O(9\times N \log N) O(9×NlogN) .


实 现 部 分 \color{red}{实现部分}

#include<bits/stdc++.h> #define reg register const int maxn = 100005; int N; int A[maxn]; int B[maxn]; int tmp[maxn]; int pos[maxn]; struct Bit_Tree{ int v[maxn], lim; void Add(int k, int x){ while(k <= lim){ v[k] = std::max(v[k], x); k += k&-k; } } int Query(int k){ if(k <= 0) return 0; int s = 0; while(k){ s = std::max(s, v[k]); k -= k&-k; } return s; } } bit_t; int main(){ scanf("%d", &N); for(reg int i = 1; i <= N; i ++) scanf("%d", &A[i]); for(reg int j = 1; j <= N; j ++) scanf("%d", &B[j]), pos[B[j]] = j; bit_t.lim = N; for(reg int i = 1; i <= N; i ++){ int dlim = std::max(1, A[i]-4), ulim = std::min(N, A[i]+4); for(reg int j = dlim; j <= ulim; j ++) tmp[j] = bit_t.Query(pos[j]-1) + 1; for(reg int j = dlim; j <= ulim; j ++) bit_t.Add(pos[j], tmp[j]); } printf("%d\n", bit_t.Query(N)); return 0; }
最新回复(0)