CF-1102-E

思路

如果 ai=aj,且bi=bj时,可知b[i]=b[i+1]=…=b[j],对b来说 [i,j] 这个区间的值是一致的
用l[x],r[x]分别代表,x这个值的边界位置(也就是最左和最右位置) 则[l[x],r[x]]这个区间是一致的
如果两个线段相交,那么相交的两个线段必然都一致
设y是不相交线段的个数,ans是解
那么 ans=2^y%mod

解决方案

/*
    @description: 
    @author: universal42@163.com
    @solution: 
        后一项等于当前项,或者比当前项大于1
        b序列使一个单调递增的序列
*/
#include<map>
#include<queue>
#include<cmath>
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define LOCAL
#define cls ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
#define Mod 998244353
#define ll long long int
#define mset(a,b) memset(a,b,sizeof(a))
#define INF 1e9
const int maxn=2e5+5;
int a[maxn];
int n;
map<int,int> r;//记录数字x最右边位置
ll pow_mod(ll a,ll b){//a^b%mod
    ll res=1;
    while(b){
        if(b&1) res=(res*a)%Mod;
        b>>=1;
        a=a*a%Mod;
    }
    return res;
}
ll getSegNum(){//获取不相交线段个数
    /*
        初始化线段个数为n,如果两个线段相交,那么用n减去  相交线段的最右边的线段的右端点减去第一个线段的左端点再加一 ,就是不相交线段的个数 
    */
    int ans=n;
    int last=-1;
    int start=0;
    for(int i=0;i<n;i++){
        if(r[a[i]]!=i){//右边端点不是自身,也就是说这个值不是单点
            last=r[a[i]];
            start=i;
            for(int j=start+1;j<=last;j++){
                if(r[a[j]]>r[a[start]]){//该区间相交
                    start=j;
                    last=r[a[j]];
                }
            }
            ans=ans-last+i;
            i=last;
        }
    }
    return ans;
}
int main() {
    //cls;
#ifdef LOCAL
    freopen("in.in","r",stdin);
#endif // LOCAL
    scanf("%d",&n);
    for(int i=0;i<n;i++){
        scanf("%d",&a[i]);
        r[a[i]]=i;
    }
    ll cnt=getSegNum();
    ll ans=pow_mod(2,cnt-1);
    printf("%lld\n",ans);
    return 0;
}
Author: universal42
Link: https://universal4s.github.io/2019/02/18/cf-1102-e/
Copyright Notice: All articles in this blog are licensed under CC BY-NC-SA 4.0 unless stating additionally.