Codeforces Round #681 (Div. 1) B. Identify the Operations

题目链接:https://codeforc.es/contest/1442/problem/B

We start with a permutation a1,a2,…,an and with an empty array b. We apply the following operation k times.

On the i-th iteration, we select an index ti (1≤ti≤n−i+1), remove ati from the array, and append one of the numbers ati−1 or ati+1 (if ti−1 or ti+1 are within the array bounds) to the right end of the array b. Then we move elements ati+1,…,an to the left in order to fill in the empty space.

You are given the initial permutation a1,a2,…,an and the resulting array b1,b2,…,bk. All elements of an array b are distinct. Calculate the number of possible sequences of indices t1,t2,…,tk modulo 998244353.

Input
Each test contains multiple test cases. The first line contains an integer t (1≤t≤100000), denoting the number of test cases, followed by a description of the test cases.

The first line of each test case contains two integers n,k (1≤k<n≤200000): sizes of arrays a and b.

The second line of each test case contains n integers a1,a2,…,an (1≤ai≤n): elements of a. All elements of a are distinct.

The third line of each test case contains k integers b1,b2,…,bk (1≤bi≤n): elements of b. All elements of b are distinct.

The sum of all n among all test cases is guaranteed to not exceed 200000.

Output
For each test case print one integer: the number of possible sequences modulo 998244353.

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

分析

我们先找到每个 b 在 a 中对应的位置 pos ,很明显如果 pos 左边和右边都是无关元素的话就有两种情况,如果只有一个无关元素的话那就只有一种情况。
怎么确定两边是否是无关元素呢,我们发现在 b 中的顺序在 x 前面的,都是 x 的无关元素(因为他们已经被选过了),那么我们可以得出:
ans = ans * ((a[pos[b[i]] - 1] < a[pos[b[i]]]) + (a[pos[b[i]] + 1] < a[pos[b[i]]])) % mod;
注意 a[i] 的意义为第 i 个数在 b 中出现的次序,如果没有出现,则为 0 。

代码
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

const ll mod = 998244353;
ll t;
ll n,k;
ll a[200007];
ll b[200007];
ll pos[200007];

int main()
{
	scanf("%lld",&t);
	while(t--)
	{
		ll ans = 1;
		scanf("%lld%lld",&n,&k);
		a[0] = a[n + 1] = INT_MAX;
		for(int i=1;i<=n;i++)
		{
			ll x;
			scanf("%lld",&x);
			pos[x] = i;
			a[i] = 0;
		}
		for(int i=1;i<=k;i++)
		{
			scanf("%lld",&b[i]);
			a[pos[b[i]]] = i;
		}
		for(int i=1;i<=k;i++)
			ans = ans * ((a[pos[b[i]] - 1] < a[pos[b[i]]]) + (a[pos[b[i]] + 1] < a[pos[b[i]]])) % mod;
		printf("%lld\n",ans);
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值