1. 程式人生 > 實用技巧 >Codeforces Round #681 (Div. 1, based on VK Cup 2019-2020 - Final) B. Identify the Operations (模擬,雙向連結串列)

Codeforces Round #681 (Div. 1, based on VK Cup 2019-2020 - Final) B. Identify the Operations (模擬,雙向連結串列)

  • 題意:給你一組不重複的序列\(a\),每次可以選擇一個數刪除它左邊或右邊的一個數,並將選擇的數append到陣列\(b\)中,現在給你陣列\(b\),問有多少種方案數得到\(b\).

  • 題解:我們可以記錄\(b_i\)\(a_i\)中的位置,然後列舉\(b_i\),取它在\(a_i\)的位置,然後看\(a_{i-1}\)\(a_{i+1}\)的情況,因為我們append之後必須要刪除\(a_{i-1}\)\(a_{i+1}\)中的一個,並且所有元素都是不重複的,所以\(a_{i-1}\)\(a_{i+1}\)必然不能出現在\(b_{i+1}...b_{n}\)中,而當我們append \(a_i\)

    之後,它也就變成了沒用的數.

    所以我們可以討論\(a_{i-1}\)\(a_{i+1}\)的情況,假如它們兩個都在\(b_{i+1}...b_{n}\)中出現,那麼我們肯定不能構造出\(b\),直接\(ans=0\)然後結束,假如它們兩個中有一個在\(b_{i+1}...b_n\)中出現,那麼我們刪除另外一個,因為刪除的方案是固定的,所以對答案沒有貢獻,假如它們兩個都沒有出現,因為\(a_{i-1},a_i,a_{i+1}\)都是沒有用的數,所以我們可以刪去\(a_{i-1}\)\(a_{i+1}\)中的任意一個,並且\(ans*=2\).
    具體實現我們可以用雙向連結串列,並且標記\(b_i,...,b_n\)

    ,每次操作後將\(b_i\)的標記刪除即可.

  • 程式碼:

#include <bits/stdc++.h>
#define ll long long
#define fi first
#define se second
#define pb push_back
#define me memset
#define rep(a,b,c) for(int a=b;a<=c;++a)
#define per(a,b,c) for(int a=b;a>=c;--a)
const int N = 1e6 + 10;
const int mod = 998244353 ;
const int INF = 0x3f3f3f3f;
using namespace std;
typedef pair<int,int> PII;
typedef pair<ll,ll> PLL;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll lcm(ll a,ll b) {return a/gcd(a,b)*b;}
 
struct misaka{
	int pre;
	int nxt;
}e[N];
 
 
int t;
int n,m;
int a[N],b[N];
int pos[N];
bool cnt[N];
 
void init(){
	rep(i,1,n){
		e[i].pre=i-1;
		e[i].nxt=i+1;
	}
	e[1].pre=0;
	e[n].nxt=0;
}
 
void Delete(int x){
	if(e[x].pre) e[e[x].pre].nxt=e[x].nxt;
	if(e[x].nxt) e[e[x].nxt].pre=e[x].pre;
}
 
int main() {
    ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
	cin>>t;
	while(t--){
		cin>>n>>m;
		rep(i,1,n) cnt[i]=false;
		rep(i,1,n){
			cin>>a[i];
			pos[a[i]]=i;
		}
		rep(i,1,m){
			cin>>b[i];
			b[i]=pos[b[i]];   //對映到a陣列的位置
			cnt[b[i]]=true;
		}
		
		init();   //雙向連結串列的初始化
		cnt[0]=true;
		int ans=1;
 
		rep(i,1,m){
			if(cnt[e[b[i]].pre]){
				if(cnt[e[b[i]].nxt]){
					ans=0;
					break;
				}
				else{
					Delete(e[b[i]].nxt);
				}
			}
			else{
				if(cnt[e[b[i]].nxt]){
					Delete(e[b[i]].pre);
				}
				else{
					ans=ans*2%mod;
					Delete(e[b[i]].nxt);
				}
			}
			cnt[b[i]]=false;
		}
		cout<<ans<<'\n';
	}
 
 
    return 0;
}