2017 多校4 Wavel Sequence

题意:

Formally, he defines a sequence \(a_1,a_2,...,a_n\) as ''wavel'' if and only if \(a_1<a_2>a_3<a_4>a_5<a_6\)...

Now given two sequences \(a_1,a_2,...,a_n\) and \(b_1,b_2,...,b_m\), Little Q wants to find two sequences \(f_1,f_2,...,f_k(1≤f_i≤n,f_i<f_{i+1})\) and \(g_1,g_2,...,g_k(1≤g_i≤m,g_i<g_i+1)\), where \(a_{f_i}=b_{g_i}\) always holds and sequence \(a_{f_1},a_{f_2},...,a_{f_k}\) is ''wavel''.

\(1<=n,m<=2000\)

\(1<=a_i,b_i<=2000\)

题解:

设\(f_{i,j,k}\)

​​ 表示仅考虑\(a[1..i]\)与\(b[1..j]\),选择的两个子序列结尾分别是\(a_i\)和\(b_j\),且上升下降状态是\(k\) 时的方案数,

则\(f_{i,j,k}=\sum f_{x,y,1-k}\)

​​ ,其中\(x<i,y<j\)

具体点说

定义\(f[i][j][0/1]\)为选择的两个子序列结尾分别是\(a_i\)和\(b_j\),当前为下降/上升状态的方案数

则当\(a[i] = b[j]\)的时候有

\(f[i][j][0] = \sum f[x][y][1]\),其中\(x < i,y < j 且a[x] < a[i]\)

\(f[i][j][1] = \sum f[x][y][0] + 1\),其中\(x < i,y < j 且a[x] > a[i]\)

暴力枚举是O(n^4)的,可以用二维树状数组去优化两维变成\(O(n^{2}log{^2}n)\)

顺序枚举i,保证了第一维递增的,只需要用树状数组去维护第二维的下标和值

#include<bits/stdc++.h>
#define LL long long
#define P pair<int,int>
using namespace std;
const int N = 2e3 + 10;
const int mod = 998244353;
int read(){
int x = 0;
char c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
return x;
}
int s[2][N][N];
int a[N],b[N];
int n,m;
void add(int &x,int y){
x += y;
if(x >= mod) x -= mod;
}
int lowbit(int x){
return x & (-x);
}
int sum(int o,int i,int j){
int ans = 0;
while(i){
int y = j;
while(y){
add(ans,s[o][i][y]);
y -= lowbit(y);
}
i -= lowbit(i);
}
return ans;
}
void update(int o,int i,int j,int val){
while(i <= n){
int y = j;
while(y <= 2000){
add(s[o][i][y],val);
y += lowbit(y);
}
i += lowbit(i);
}
}
int main(){ int T;
T = read();
while(T--){
n = read(),m = read();
for(int k = 0;k < 2;k++)
for(int i = 1;i <= n;i++)
for(int j = 1;j <= 2000;j++) s[k][i][j] = 0;
for(int i = 1;i <= n;i++) a[i] = read();
for(int i = 1;i <= m;i++) b[i] = read();
int ans = 0;
for(int i = 1;i <= m;i++){
for(int j = 1;j <= n;j++){
if(b[i] == a[j]){
int tmp1 = sum(1,j-1,a[j]-1),tmp2 = (mod + sum(0,j-1,2000)-sum(0,j-1,a[j]))%mod;
update(0,j,a[j],tmp1);/// 0 下降 1 上升
update(1,j,a[j],(tmp2 + 1)%mod);
add(ans,tmp1);
add(ans,tmp2);
add(ans,1);
}
}
}
printf("%d\n",ans);
}
return 0;
}

题解的\(O(n^2)\)的做法

用\(s[i][j][0/1]\)表示\(a\)和\(b\)分别在\(1\)$i$和$1$\(j\)的结尾的子序列的方案

那么\(dp[i][j][k] = s[i-1][j-1][1 - k] + k==1?1:0\)

\(i,j\)顺序枚举,遇到\(a[i] = b[j]\)的时候,前面可以顺便计算大于和小于它的方案,然后更新即可

#include<bits/stdc++.h>
#define LL long long
#define P pair<int,int>
using namespace std;
const int N = 2e3 + 10;
const int mod = 998244353;
int read(){
int x = 0;
char c = getchar();
while(c < '0' || c > '9') c = getchar();
while(c >= '0' && c <= '9') x = x * 10 + c - 48, c = getchar();
return x;
}
int s[2][N][N];
int dp[2][N][N];
int a[N],b[N];
int n,m;
void add(int &x,int y){
x += y;
if(x >= mod) x -= mod;
}
int main(){ int T;
T = read();
while(T--){
n = read(),m = read();
for(int i = 1;i <= n;i++) a[i] = read();
for(int i = 1;i <= m;i++) b[i] = read();
for(int k = 0;k < 2;k++)
for(int i = 1;i <= n;i++)
for(int j = 1;j <= m;j++) dp[k][i][j] = s[k][i][j] = 0;
int ans = 0;
for(int i = 1;i <= n;i++){
int tmp0 = 0,tmp1 = 0;///0 下降 1 上升
for(int j = 1;j <= m;j++){
if(a[i] == b[j]){
add(dp[0][i][j],tmp0);
add(dp[1][i][j],(tmp1+1)%mod);
add(ans,(dp[0][i][j]+dp[1][i][j])%mod);
}
else if(a[i] > b[j]){
add(tmp0, s[1][i-1][j]);
}else{
add(tmp1,s[0][i-1][j]);
}
}
for(int j = 1;j <= m;j++){
s[0][i][j] = s[0][i-1][j];
s[1][i][j] = s[1][i-1][j];
if(a[i] == b[j]){
add(s[0][i][j],dp[0][i][j]);
add(s[1][i][j],dp[1][i][j]);
}
}
}
printf("%d\n",ans);
}
return 0;
}

2017 多校4 Wavel Sequence的更多相关文章

  1. 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] 要求满 ...

  2. hdu6078 Wavel Sequence dp+二维树状数组

    //#pragma comment(linker, "/STACK:102400000,102400000") /** 题目:hdu6078 Wavel Sequence 链接:h ...

  3. 2017 多校5 hdu 6093 Rikka with Number

    2017 多校5 Rikka with Number(数学 + 数位dp) 题意: 统计\([L,R]\)内 有多少数字 满足在某个\(d(d>=2)\)进制下是\(d\)的全排列的 \(1 & ...

  4. 2017 多校5 Rikka with String

    2017 多校5 Rikka with String(ac自动机+dp) 题意: Yuta has \(n\) \(01\) strings \(s_i\), and he wants to know ...

  5. 2017 多校4 Security Check

    2017 多校4 Security Check 题意: 有\(A_i\)和\(B_i\)两个长度为\(n\)的队列过安检,当\(|A_i-B_j|>K\)的时候, \(A_i和B_j\)是可以同 ...

  6. 2017 多校3 hdu 6061 RXD and functions

    2017 多校3 hdu 6061 RXD and functions(FFT) 题意: 给一个函数\(f(x)=\sum_{i=0}^{n}c_i \cdot x^{i}\) 求\(g(x) = f ...

  7. 2017 多校2 hdu 6053 TrickGCD

    2017 多校2 hdu 6053 TrickGCD 题目: You are given an array \(A\) , and Zhu wants to know there are how ma ...

  8. 2017 多校1 I Curse Myself

    2017 多校2 I Curse Myself(第k小生成树) 题目: 给一张带权无向连通图,该图的任意一条边最多只会经过一个简单环,定义\(V(k)为第k小生成树的权值和\),求出\(\sum_{k ...

  9. hdu6136[模拟+优先队列] 2017多校8

    有点麻烦.. /*hdu6136[模拟+优先队列] 2017多校8*/ #include <bits/stdc++.h> using namespace std; typedef long ...

随机推荐

  1. ref是什么?

    ref是组件的特殊属性,组件被渲染后,指向组件的一个引用.可以通过组件的ref属性,来获取真实的组件. 因为,组件并不是真正的DOM节点,而是存在于内存中的一种数据结构,称为虚拟的DOM,只有当它真正 ...

  2. Tinyhttpd 知识点

    1. fork 子进程 #include <stdio.h> #include <unistd.h> int main(void) { pid_t pid; ; pid = f ...

  3. 微信网页授权access_token与基础支持的access_token

    问题1:网页授权access_token与分享的jssdk中的access_token一样吗? 答:不一样.网页授权access_token 是一次性的,而基础支持的access_token的是有时间 ...

  4. Altium Designer使用5:AD18的DXP在什么地方?

    1.在顶上的菜单栏右击

  5. C++高级 STL——模板函数、模板类

    1.模板函数 // 定义 template <class T> Max(T &t1, T &t2) { return ((t1 > t2) ? t1 : t2); } ...

  6. NOI P1896 互不侵犯 状压DP

    题目描述 在N×N的棋盘里面放K个国王,使他们互不攻击,共有多少种摆放方案.国王能攻击到它上下左右,以及左上左下右上右下八个方向上附近的各一个格子,共8个格子. 注:数据有加强(2018/4/25) ...

  7. 013---Django的分页器

    知识预览 分页 Django的分页器(paginator) view from django.shortcuts import render, HttpResponsefrom app01.model ...

  8. centos安装Linux

    CentOS下安装Redis Redis是一种高级key-value数据库.它跟memcached类似,不过数据可以持久化,而且支持的数据类型很丰富.有字符串,链表,集 合和有序集合.支持在服务器端计 ...

  9. Linux两种方式rd.break和init重置root管理员密码

    centos7/rhel7进入单用户方式和重置密码方式发生了较大变化,GRUB由b引导变成了ctrl+x引导. 重置密码主要有rd.break和init两种方法. rd.break方法: 1.启动的时 ...

  10. 4-linux基本命令

    1. cd命令 cd 回当前用户 家目录   cd /home  进入home目录 (绝对路径)   (相对路径)   cd –  上一目录和当前目录来回切换(主要用于返回上一目录)   cd .   ...