HDU 6078 - Wavel Sequence | 2017 Multi-University Training Contest 4
/* HDU 6078 - Wavel Sequence [ DP ] | 2017 Multi-University Training Contest 4 题意: 给定 a[N], b[M] 要求满足 a[f(1)]<a[f(2)]>a[f(3)]<a[f(4)]>a[f(5)]<a[f(6)]... b[g(i)] == a[f(i)] f(i) < f(i+1), g(i) < g(i+1) 的子序列 的数目 分析: dp[i][j][0] 表示 以a[i], b[j]结尾的且为波谷的情况总和,dp[i][j][1] 为波峰 对于某个 i,j满足 a[i] == b[j] dp[i][j][0] = sum(dp[x][y][1]), x < i && y < j && b[y] > a[i] 设 sum[i-1][y][1] = ∑dp[x][y][1] , x <= i-1 则 dp[i][j][0] = ∑ sum[i-1][y][1], b[y] > a[i] 对于每一个 b[j], sum[i][j] 累计了前i个的a[i]的影响,求出每次dp[i][j]后O(1)更新即可 即 sum[i][j][1] = sum[i-1][j][1] + dp[i][j][1] 然后对于某一个a[i]的所有b[j],可以以前缀和的形式,利用sum[i-1][y],O(n)全部更新 所以复杂度O(n^2) */ #include <bits/stdc++.h> using namespace std; const int MOD = 998244353; const int N = 2005; int t, n, m; int a[N], b[N]; int dp[N][2]; int sum[N][2]; int main() { 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]); memset(sum, 0, sizeof(sum)); long long ans = 0; for (int i = 1; i <= n; i++) { int cnt0 = 0, cnt1 = 0; for (int j = 1; j <= m; j++) { if (a[i] == b[j]) { dp[j][0] = cnt1 + 1; dp[j][1] = cnt0; ans = (ans + cnt1+cnt0+1) % MOD; } else if (b[j] > a[i]) cnt1 = (cnt1+ sum[j][1]) % MOD; else cnt0 = (cnt0+ sum[j][0]) % MOD; } for (int j = 1; j <= m; j++) if (a[i] == b[j]) { sum[j][0] = (sum[j][0] + dp[j][0]) % MOD; sum[j][1] = (sum[j][1] + dp[j][1]) % MOD; } } printf("%lld\n", ans); } }
我自倾杯,君且随意