zoukankan      html  css  js  c++  java
  • Codeforces Round #681 (Div. 1, based on VK Cup 2019-2020

    • 题意:给你一组不重复的序列(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<<'
    ';
    	}
     
     
        return 0;
    }
    
  • 相关阅读:
    源码阅读(18):Java中主要的Map结构——HashMap容器(中)
    源码阅读(17):红黑树在Java中的实现和应用
    java中创建文件并写入的方法
    源码阅读(16):Java中主要的Map结构——HashMap容器(上)
    源码阅读(15):Java中主要的Map结构——概述
    从源码分析:Java中的AQS
    源码阅读(14):Java中主要的Queue、Deque结构——PriorityQueue集合(下)
    源码阅读(13):Java中主要的Queue、Deque结构——PriorityQueue集合(中)
    java 归并排序与快速排序
    python中的容器、可迭代对象、迭代器、生成器
  • 原文地址:https://www.cnblogs.com/lr599909928/p/14074570.html
Copyright © 2011-2022 走看看