P13662 「TPOI-5A」Luminescence

题目描述

有一个长度为 \(n\),元素大小为 \(0\to n-1\) 的排列 \(q\)。给出它的最小前缀和后缀数组,求其所有可能的 \(q\)\(\sum_{1\le l\le r\le n}\operatorname{mex}_{l\le i\le r}q_i\) 之和。答案对 \(998244353\) 取模。

题解

首先发现了只要最小前缀和后缀数组是确定的,我们的任意 \(q\) 的权值都是一样的。为什么?我们不用出题人的 trick 解释,我们换一种:

  • 先找到确定的数,我们从小到大找被确定的数,发现只有都包含这些数,这个区间才有贡献。
  • 如果一个数是确定的,那么一定在当前最小包含所有确定的数的区间外。
  • 同理,不确定的数一定在当前包含的区间以内。证明:如果在区间外,那么一定有一个在这个不确定的数之外的更小的数,但是这个更小的数是被包含在区间内的,与假设不同,证毕。

所以我们只需要确定不确定的数有多少种填放可能。

根据上面的性质,我们在确定区间时同时计算方案数。因为这个数一定在区间内,而在区间内有没有其他限制。所以我们有以下方案:

  • 我们每有一个不确定的数 \(i\) 时,若当前最小的包含所有数的区间为 \([l,r]\),则方案数会乘上 \(r-l-i+1\)
  • 我们每有一个确定的数时,我们更新区间,并且所有包含这个区间的方案贡献 \(+1\),用容斥计算这个贡献就可以了。

code:

#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e6+10,mod=998244353;
int n,m,q,T,a[N],b[N],c[N],d[N],cnt;
signed main(){
    ios::sync_with_stdio(0);
    cin.tie(0),cout.tie(0);
    cin>>T;
    while(T--){
        cin>>n;
        int ans=0, pw=1;
        for(int i=0;i<n;i++) c[i]=0;
        for(int i=1;i<=n;i++) cin>>a[i];
        for(int i=1;i<=n;i++) cin>>b[i];
        c[a[1]]=1;c[b[n]]=n;int l=c[0], r=c[0];
        for(int i=2;i<=n;i++){if(a[i-1]!=a[i]) c[a[i]]=i;}
        for(int i=n-1;i>=1;i--){if(b[i+1]!=b[i]) c[b[i]]=i;}
        for(int i=0;i<n;i++){
            if(c[i]){l=min(c[i],l);r=max(c[i],r);}
			else pw=pw*(r-l+1-i)%mod;
            ans=(ans+l*(n-r+1)%mod)%mod;
        }cout<<ans*pw%mod<<'\n';
    }
    return 0;
}
posted @ 2025-10-15 12:52  NeeDna  阅读(7)  评论(0)    收藏  举报