【题解】ARC215 D - Unique Subsequence
题意:给你一个序列 a a a 找到只在 a a a 序列中出现一次的子序列数量。
solution:
考虑怎么去重。
首先满足条件的序列一定是包含在
a
a
a 的子序列中的。
设 dp[i] 表示必选第 i 个字符,满足条件的不同子序列数量。
先说转移方程:
d
p
[
i
]
=
∑
d
p
[
j
]
dp[i]=\sum dp[j]
dp[i]=∑dp[j] , 其中 j 满足 : 对于任意
k
∈
[
i
+
1
,
j
−
1
]
k\in [i+1,j-1]
k∈[i+1,j−1] ,
a
[
k
]
≠
a
[
i
/
j
]
a[k]\ne a[i/j]
a[k]=a[i/j]
解释一下,首先如果满足 a[k]=a[i/j] ,那么可以将 i/j 其中之一替换成 k 得到相同的子序列,肯定是不合法的;其次这样的序列一定是唯一存在的,证明:从后往前 select 保证字典序最大,必须 select 直到 0;从前往后 select 保证字典序最小,必须 select 直到 n+1 ,保证字典序最小,两种得到的序列是唯一个。
最后答案是
∑
d
p
[
l
s
t
[
i
]
]
\sum dp[lst[i]]
∑dp[lst[i]] 。用线段树维护即可。
代码极短,思维极难。
#include<bits/stdc++.h>
#define ll long long
#define INF 0x3f3f3f3f
#define PII pair<int,int>
using namespace std;
const int mx=2e5+5;
const int mod=998244353;
int n,dp[mx],lst[mx],t[mx<<2];
void PushUp(int p) {t[p]=(t[p<<1]+t[p<<1|1])%mod;}
void add(int &x,int y) {x+=y; if(x>mod) x-=mod;}
void upd(int p,int l,int r,int x,int y) {
if(l==r) {t[p]=y;return;}
int mid=l+r>>1; x<=mid?upd(p<<1,l,mid,x,y):upd(p<<1|1,mid+1,r,x,y);
PushUp(p);
}
int qry(int p,int l,int r,int ql,int qr) {
if(ql<=l&&r<=qr) return t[p];
int mid=l+r>>1,res=0; if(ql<=mid) add(res,qry(p<<1,l,mid,ql,qr));
if(mid<qr) add(res,qry(p<<1|1,mid+1,r,ql,qr));
return res;
}
signed main() {
cin>>n; upd(1,1,n+1,1,1);
for(int i=2;i<=n+1;i++) {
ll x; cin>>x;
dp[i]=qry(1,1,n+1,lst[x],i);
if(lst[x]) upd(1,1,n+1,lst[x],0);
lst[x]=i; upd(1,1,n+1,i,dp[i]);
}
int res(0);
for(int i=1;i<=n;i++) {
if(lst[i]) add(res,dp[lst[i]]);
}
printf("%d",res);
}

浙公网安备 33010602011771号