题意:
序列a有n个数,序列b有m个数。问,两个序列有多少个公共子序列满足“波浪状”。“波浪状”数组形如 a1 < a2 > a3 < a4 > a5 ……
1 <= n,m <= 2000
分析:
看了一个博客分析的非常好
http://blog.csdn.net/weyoungg/article/details/76735843
代码就是按照这个博主的思路,只不过用滚动数组把第一维滚掉了。
代码:
#include <iostream>
#include <algorithm>
#include <queue>
#include <stack>
#include <vector>
#include <set>
#include <cmath>
#include <cstdlib>
#include <cstring>
#include <cstdio>
using namespace std;
#define ms(a,b) memset(a,b,sizeof(a))
typedef long long ll;
const int MAXN = 2005;
const double EPS = 1e-8;
const int INF = 0x3f3f3f3f;
const int MOD = 998244353;
int n, m, a[MAXN], b[MAXN];
ll f[MAXN][2];
int main() {
int T;
scanf("%d", &T);
while (T--) {
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &a[i]);
for (int i = 1; i <= m; i++) scanf("%d", &b[i]);
ms(f, 0);
ll ans = 0;
//f[][1] 波峰 f[][0] 波谷
for (int i = 1; i <= n; i++) {
ll top = 1, btm = 0;
for (int j = 1; j <= m; j++) {
if (a[i] == b[j]) {
f[j][0] += top;
f[j][1] += btm;
ans = (ans + top + btm) % MOD;
} else if (a[i] > b[j]) {
(btm += f[j][0]) %= MOD;
} else {
(top += f[j][1]) %= MOD;
}
}
}
printf("%lld\n",ans);
}
return 0;
}