hdu6087 dp

来源:互联网 发布:淘宝手机详情添加链接 编辑:程序博客网 时间:2024/06/15 18:21

类似于最长公共上升子序列,对于每个i,只考虑存在j使得a[i]==b[j]的情况。
dp[i][j][0]表示以a[i]和b[j]为公共序列结尾且为波谷的情况总和。
dp[i][j][1]则表示波峰的情况总和。
S[i][j][0]表示sum(dp[k][j][0] | 1<=k<=j-1)。
S[i][j][1]则表示sum(dp[k][j][1] | 1<=k<=j-1)。
那么对于每个a[i],只有存在j使得b[j]==a[i]时,dp[i][j][0]等于sum(S[i-1][k][1] | 1<=k<=j-1&&b[k]>a[i])+1,dp[i][j][1]等于sum(S[i-1][k][0] | 1<=k<=j-1&&b[k]<=a[i]-1).
可以用滚动数组优化掉一维空间。

代码:

#include<bits/stdc++.h>#define fi first#define se second#define pb push_back#define CLR(A, X) memset(A, X, sizeof(A))using namespace std;typedef long long LL;typedef pair<int, int> PII;const double eps = 1e-10;int dcmp(double x){if(fabs(x)<eps) return 0; return x<0?-1:1;}const LL INF = 0x3f3f3f3f;const LL MOD = 998244353;const int N = 2e3+5;int b[N], a[N];LL sum[N][2], dp[N][2];int main() {//    freopen("1001.txt", "r", stdin);    int T, n, m;    scanf("%d", &T);    while(T--) {        CLR(sum, 0); CLR(dp, 0);        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]);        LL ans = 0;        for(int i = 1; i <= n; i++) {            LL cnt1 = 1, cnt0 = 0;            for(int j = 1; j <= m; j++) {                dp[j][0] = dp[j][1] = 0;                if(a[i] == b[j]) {                    dp[j][0] = cnt1;                    dp[j][1] = cnt0;                    ans = (ans+cnt1+cnt0)%MOD;                }                else if(b[j] < a[i]) (cnt0 += sum[j][0]) %= MOD;                else (cnt1 += sum[j][1]) %= MOD;            }            for(int j = 1; j <= m; j++) {                if(b[j] == a[i]) {                    (sum[j][0] += dp[j][0]) %= MOD;                    (sum[j][1] += dp[j][1]) %= MOD;                }            }        }        printf("%lld\n", ans);    }    return 0;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52