【题解】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,j1] 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); }

__EOF__

本文作者仰望星空的蚂蚁
本文链接https://www.cnblogs.com/cqbzly/p/17530260.html
关于博主:评论和私信会在第一时间回复。或者直接私信我。
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   仰望星空的蚂蚁  阅读(3)  评论(0编辑  收藏  举报  
相关博文:
阅读排行:
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· DeepSeek 开源周回顾「GitHub 热点速览」
点击右上角即可分享
微信分享提示