CF1574F Occurrences 题解
CF1574F Occurrences
题意
定义
有
求不同的
数据范围:
题解
容易发现,如果
其次,我们填完
当然,这条链上必须不能包含环,例如
所以,把图建出来之后,每个连通块分别考虑,只有该连通块是一条链的时候才能被选,所占的长度是连通块的大小(元素个数)。而不同的连通块大小最多
具体的,记
时间复杂度
具体的实现上,使用并查集,维护每个集合的
可以参考代码。
#include <bits/stdc++.h>
using namespace std;
const int N=3e5+5,mod=998244353;
inline void Add(int &a,int b){a+=(a+b>=mod)?b-mod:b;}
int fa[N],sz[N],to[N],a[N],n,m,k,pre[N],tag[N];
int find_fa(int x){return fa[x]==x?x:fa[x]=find_fa(fa[x]);}
inline void merge(int x,int y){
int fy=find_fa(y),fx=find_fa(x);
if(fy==fx){tag[fx]=1;return;}
fa[fy]=fx;
sz[fx]+=sz[fy];
tag[fx]|=tag[fy];
}
int buc[N],tot,g[N],f[N];
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=1;i<=k;++i)fa[i]=i,sz[i]=1;
for(int i=1,c;i<=n;++i){
scanf("%d",&c);
for(int j=1;j<=c;++j){
scanf("%d",&a[j]);
if(j==1)continue;
if((pre[a[j]]&&pre[a[j]]!=a[j-1])||(to[a[j-1]]&&to[a[j-1]]!=a[j])){
merge(a[j-1],a[j]);
tag[find_fa(a[j])]=1;
}else if(!to[a[j-1]]){
to[a[j-1]]=a[j];
pre[a[j]]=a[j-1];
merge(a[j-1],a[j]);
}
}
}
for(int i=1;i<=k;++i){
if(find_fa(i)!=i||tag[i])continue;
++g[sz[i]];
}
for(int i=1;i<=k;++i)if(g[i])buc[++tot]=i;
f[0]=1;
for(int i=0;i<=m;++i)
for(int j=1;j<=tot&&i+buc[j]<=m;++j)
f[i+buc[j]]=(f[i+buc[j]]+1ll*f[i]*g[buc[j]])%mod;
printf("%d\n",f[m]);
return 0;
}