hud 6078 Wavel Sequence
题目大意:给你两个序列a,b,让你找出两个函数 f 和 g 使得 a[f]=b[g],并且a[f1],a[f2],a[f3]……a[fk]满足 序列a1 < a2 > a3 < a4……为你满足关系的 f 和 g有多少种
解题思路:不难想到我们可以单独考虑每个数字,看它作为波峰有多少种情况,波谷有多少种情况,然后求和。但是具体怎么求每个数字作为波峰的情况和波谷的情况呢?因为我们要用a数组来构造波浪,所以我们不妨可以将a数组固定,然后根据条件在b数组中寻找a中每个数据可能作为波峰和波谷的所有情况。具体要怎么做看代码
#include <bits/stdc++.h>
using namespace std;
const int mod = 998244353;
int dp[2005][2],sum[2005][2];
/**
dp[][0]用来保存b数组中这个值作为波谷的情况
dp[][1]用来保存b数组中这个值作为波峰的情况
sum[][0]用来保存b数组中这个值作为波谷的总情况
sum[][1]用来保存b数组中这个值作为波峰的总情况
*/
int main()
{
int T;scanf("%d",&T);
while(T--){
memset(dp,0,sizeof(dp));
memset(sum,0,sizeof(sum));
int n,m,a[2005],b[2005];
scanf("%d %d",&n,&m);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int j = 1; j <= m;j++)
scanf("%d",&b[j]);
long long ans = 0,cnt0,cnt1;///ans用来存f和g共有多少种选择,从cnt1用来保存当前值做波峰的情况,cnt0用来保存做波谷的情况
for(int i=1;i<=n;i++){
cnt0 = 1;cnt1 = 0;///因为每个数字都可以单独作为波谷,所以波谷初始值为1.
for(int j = 1; j <= m; j ++){
dp[j][0] = dp[j][1] = 0;
if(a[i] == b[j])///表示此时已经找到一组可以为波浪的数据,并将这个波峰,波谷的值记下,方便后边使用,ans要累加上
{
dp[j][0] = cnt0;
dp[j][1] = cnt1;
ans = (ans + cnt0 + cnt1)%mod;
}
else if(a[i] > b[j])///如果当前这个值比a[i]要小的话说明a[i]可以作为波峰,这个时候它可以承接前边所有的波谷的情况,所以要加上前边波谷的所有情况
cnt1 = (cnt1 + sum[j][0])%mod;
else///如果当前这个值比a[i]要大的话说明a[i]可以作为波谷,这个时候它可以承接前边所有的波峰的情况,所以要加上前边波谷的所有情况
cnt0 = (cnt0 + sum[j][1])%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);
}
return 0;
}