链接
题意:
给定长度为 n n n的序列 a a a,问有多少 a a a的子序列 b b b,满足在 a a a的子序列中只出现一次。
分析:
首先我们看到,子序列,那么我们想到如何使他唯一,我们发现,如果 我们找到以x结尾的子序列,在后面还有x那么一定不是唯一的, 举个例子1 2 11 3 4 5 6 3 4
我们以3结尾,1 2 11 3
在其后第8个位置还有一个3所以还可以1 2 11 3(8)
.这样就不符合条件。
那么我们只能考虑同样数字最后一个位置。这样才能保证只出现一次。
如果出现
a
i
,
a
j
a_i,a_j
ai,aj相等且
(
i
<
j
)
(i<j)
(i<j)那么我们知道
a
j
a_j
aj 我们知道答案是f[j]= 结尾是j的方案数-结尾是i的方案数
之后我们用树状数组维护。
ll n,f[maxn],a[maxn],last[maxn],pre[maxn],ne[maxn];
struct BIT {///树状数组
ll c[maxn];
void add(int x,ll d){
while(x<=n+1){
c[x]+=d;
c[x]%=MOD;
x+=lowbit(x);
}
}
ll query(int x){
ll ans=0;
while(x){
ans+=c[x];
ans%=MOD;
x-=lowbit(x);
}
return ans;
}
}bit;
void init(){
}
void solve()
{
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
if(last[a[i]]) {///存在前驱节点,
ne[last[a[i]]]=i;///将其链接后继节点,
pre[i]=last[a[i]];///将其链接前驱节点。
}
last[a[i]]=i;//更新
}
ll ans=0;
bit.add(1,1);///初始一个字符一个方案
for(int i=1;i<=n;i++){
f[i]=(bit.query(i)-bit.query(pre[i])+MOD)%MOD;///区间方案数
if(pre[i]) bit.add(pre[i]+1,-f[pre[i]]);///存在前驱,减去
if(!ne[i]) ans=(ans+f[i]+MOD)%MOD;///没有后继节点,那这个就是以 该数字结尾的答案
bit.add(i+1,f[i]);///后面都会增加 f[i]的方案
}
cout<<ans<<endl;
}