CodeForces - 1442B

题目
在这里插入图片描述
Example
input
3
5 3
1 2 3 4 5
3 2 5
4 3
4 3 2 1
4 3 1
7 4
1 4 7 3 6 2 5
3 2 4 5

output
2
0
4

Note
在这里插入图片描述

题意
有两行数字,每一行都不存在重复数字(两行数字互不影响);
一种操作:任意选择一个数字X,然后选择它左边或者右边的一个数字Y(下标满足 1-n),把Y添加到数组b(初始为空)的最后一个数字之后,之后删掉这个数字X(删除后右边的数字依次左移补齐),要求最后获得和第二行数字一样的排列
问:一共有多少种方法;


思路
首先:对于一个数字a,如果它出现在第二行数字中,并且还没有轮到,那么这个数字绝对不能删掉(数字不重复);
其次:对于当前正在考虑的第二行的数字 a ,由于我们希望通过操作从第一行数字中找到a并放到b数组里,那么我们只能选择第一行数字中 a 的左右两个数字的其中一个(如果存在),如果两个数字都没有出现在a的后面(这个后面指:某个数字存在于第二行数字中,且在a的后面),那么就有两种情况,对于每一种情况,我们删掉一个数字,但同时我们也增加了一个数字(增加是指:本来数字a是不能被删除的,但是经过这次操作后,数字a已经存在于数组b中了,那么也就可以删掉了),所以对于其他数字来说,并没有任何影响,所以只要依次乘过去取模就是答案了


例子
以样例1为例:
5 3
1 2 3 4 5
3 2 5
第二行第一个数字是3,它在第一行中只有一个选择,就是选择4(2比3出现的晚,不能选择),操作完后剩下 1 2 3 5,由于3已经存在于数组b中,也就是说,3现在也可以被删除(选择)了,那不就相当于把4换成了3(只是换了个数字而已),对5来说没有造成任何影响(还是只能选择左边的一个数字),对2来说也没造成任何影响(依然能选择两个数字)


代码

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define mod 998244353
#define maxn 200005

int s[maxn], id[maxn], ss[maxn]; //s第一行数字 id每个数字在第一行数字中出现的位置 ss第二行数字
bool vis[maxn]; //数字是否可 选择/删除
ll ans=1;

int main(){
	int T; cin>>T;
	while(T--){
		int n, m; cin>>n>>m;
		for(int i=1;i<=n;++i) vis[i]=0;
		for(int i=1;i<=n;++i) cin>>s[i], id[s[i]]=i;
		for(int i=1;i<=m;++i) cin>>ss[i], vis[ss[i]]=1;
		ans=1;
		for(int i=1;i<=m;++i){
			int nw=id[ss[i]];
			ll sum=0;
			if(nw-1>0){
				if(!vis[s[nw-1]]) sum++;
			}
			if(nw+1<=n){
				if(!vis[s[nw+1]]) sum++;
			}
			vis[ss[i]]=0;
			ans=ans*sum%mod;
		}
		cout<<ans<<endl;
	}
	
	return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值