HDU 6078 Wavel Sequence

链接:http://acm.hdu.edu.cn/showproblem.php?pid=6078

题意:找出两个序列中相同的子序列,且子序列满足a1<a2>a3<a4>a5……

思路:可以知道所谓子序列是从波谷开始的,当子序列只有一个元素时,他是自己的波谷,代码中我们可以用n^2的复杂度,对两个数列扫描,因为有这样一个性质,新扫到一个数字的话,如果这个数字在两个序列中都有,对于这两个相同数字之前的两个序列而言也是有可行解的,那这个相同数字是可以添加到可行解子串的后面变成波峰或者波谷;

例如:1 5 3和4 1 1 5 3

当a数列扫描到3的时候可知道之前是有可行解的两个(1,1)和两个(1,5    1,5)这个时候,(5,5)之所以是前面的解但是在此不能用的原因是因为子序列要从波谷开始,所以为了复杂度,这些东西要在扫的时候记录下来:

dp[0][j]是扫当前一轮,b数列的第j为波谷的情况,s[0][j]是扫到当前轮为止,b数列的第j为波谷的情况;

dp[1][j]是扫当前一轮,b数列的第j为波封的情况,s[1][j]是扫到当前轮为止,b数列的第j为波峰的情况;

中间的ans是暂存变量,虽然发现,只要a[i]和b[j]有大小关系的时候,ans就会加上s数组里面的数,但是发现,只有在相等的时候才会更新;这里不是很好理解,但是也是这个题的巧妙之处,我就假设我扫的当前a【i】在b中存在一个b【k】和它相等,所以,我扫描这个b【k】之前的元素时候,比较a【i】和b【j】大小的时候,就相当于比较b【j】和b【k】的大小,以此决定b【k】是否可以接在b【j】的后面成为新的可行解,而直到找到这个b【k】我才会更新值。

代码:

#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
typedef long long LL;
const LL mod=998244353;
const int maxn=2005;
int a[maxn],b[maxn];
LL dp[2][maxn],s[2][maxn];

int main()
{
    freopen("input.txt","r",stdin);
    int t;
    scanf("%d",&t);
    while(t--)
    {
        memset(dp,0,sizeof dp);
        memset(s,0,sizeof s);
        int n,m;
        scanf("%d%d",&n,&m);
        for(int i=0;i<n;i++)scanf("%d",a+i);
        for(int i=0;i<m;i++)scanf("%d",b+i);
        LL sum=0;
        for(int i=0;i<n;i++)
        {
            LL ans0=1;//作为波谷的情况
            LL ans1=0;//作为波峰的情况
            for(int j=0;j<m;j++)
            {
                if(a[i]==b[j])
                {
                    dp[0][j]=ans0;
                    dp[1][j]=ans1;//遇到相等就要更新
                    sum=(sum+ans1+ans0)%mod;
                }
                else if(a[i]>b[j])
                {
                    ans1+=s[0][j]%=mod;
                }
                else
                {
                    ans0+=s[1][j]%=mod;
                }
            }
            for(int j=0;j<m;j++)
            {
                if(a[i]==b[j])
                {
                    s[0][j]+=dp[0][j]%=mod;
                    s[1][j]+=dp[1][j]%=mod;
                }
            }
        }
        printf("%lld\n",sum);
    }
    return 0;
}
时间: 2024-10-12 12:34:32

HDU 6078 Wavel Sequence的相关文章

2017多校第4场 HDU 6078 Wavel Sequence DP

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6078 题意:求两个序列的公共波形子序列的个数. 解法: 类似于最长公共上升子序列,对于每个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

hdu6078 Wavel Sequence dp+二维树状数组

//#pragma comment(linker, "/STACK:102400000,102400000") /** 题目:hdu6078 Wavel Sequence 链接:http://acm.hdu.edu.cn/showproblem.php?pid=6078 题意:给定a序列和b序列.从a中取一个子序列x(数的位置顺序保持不变),子序列每个数满足a1<a2>a3<a4>a5<a6... 波浪形 从b中取相同长度的子序列y,也满足波浪形. 如果x

HDU 5014 Number Sequence(2014 ACM/ICPC Asia Regional Xi&#39;an Online) 题解

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5014 Number Sequence Problem Description There is a special number sequence which has n+1 integers. For each number in sequence, we have two rules: ● ai ∈ [0,n] ● ai ≠ aj( i ≠ j ) For sequence a and sequ

hdu 4441 Queue Sequence(splay)

题目链接:hdu 4441 Queue Sequence 这题看了题解写的,题解传送门 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 #define ls l,m,rt<<1 4 #define rs m+1,r,rt<<1|1 5 using namespace std; 6 typedef long long ll; 7 8 const int N=1e6+7; 9 i

hdu 5297 Y sequence(容斥)

题目链接:hdu 5297 Y sequence 考虑62以内的指数,x为奇数个质数因子,就减掉,偶数个加上.计算x为指数的不满足数直接pow(n,1/x)即可. #include <cstdio> #include <cstring> #include <cstdlib> #include <cmath> #include <vector> #include <algorithm> using namespace std; type

KMP算法的定义及KMP练手题 HDU 1711 Number Sequence (我的模板代码)

题意:就是要你来找出b数组在a数组中最先匹配的位置,如果没有则输出-1 思路:直接KMP算法(算法具体思想这位牛写的不错http://blog.csdn.net/v_july_v/article/details/7041827) AC代码: #include<cstdio> #include<cstring> #include<stdlib.h> #include<iostream> using namespace std; #define maxn 100

hdu 5306 Gorgeous Sequence(区间最值更新+求和)

题目链接:hdu 5306 Gorgeous Sequence 题意: 给你一个序列,有三种操作. 0 x y t:将[x,y]的数取min(a[i],t) 1 x y:求[x,y]的最大值 2 x y:求[x,y]的区间和 题解: 吉老师的课件题:传送门 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;i++) 3 #define ls l,m,rt<<1 4 #define rs m+1,r,rt

hdu 6025 Coprime Sequence (前后缀GCD)

题目链接:hdu 6025 Coprime Sequence 题意: 给你n个数,让你删掉一个数,使得剩下的数的gcd最大 题解: 先将这一列数的前缀后缀gcd预处理一下. 然后挨着for一下就行了 1 #include<bits/stdc++.h> 2 #define F(i,a,b) for(int i=a;i<=b;++i) 3 using namespace std; 4 5 const int N=1e5+7; 6 int t,pre[N],suf[N],n,a[N]; 7 8

hdu 5014 Number Sequence(贪心)

题目链接:hdu 5014 Number Sequence 题目大意:给定n,表示有0~n这n+1个数组成的序列a,要求构造一个序列b,同样是由0~n组成,要求∑ai⊕bi尽量大. 解题思路:贪心构造,对于n来说,找到n对应二进制的取反对应的数x,那么从x~n之间的数即可两两对应,然后x-1即是一个子问题. #include <cstdio> #include <cstring> #include <algorithm> using namespace std; con