HDU 6078

/*
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
", ans);
    }
}

  

我自倾杯,君且随意
原文地址:https://www.cnblogs.com/nicetomeetu/p/7293749.html