[ARC128D](计数dp)
1.CF1656E(构造思想)2.P10178(构造思想)3.P10179(构造思想+实现)4.P3963 (平衡树思想)5.P10156(dp思想)6.P3939 (ds实现)7.CF776D(并查集思想)8.CF243A (拆位思想)9.ABC283E (dp思想)10.AT_joi2015ho_b (dp思想)11.P9588 (ds思想)12.CF482B (拆位思想+实现)13.U332154 carbon 题解(期望)14.U329011 trie pi 题解
15.[ARC128D](计数dp)
16.P1081 (倍增+代码实现技巧)17.CF1537D (博弈论+找规律)18.CF1557D (dx)(dp技巧)19.P3165/P2596(文艺平衡树套路)20.吉司机大杂烩21.ARC149C (构造)22.CF19D(树套树)23.网络流大杂烩24.U417376题解25.CF1748E(笛卡尔树)26.[CERC2019] Be Geeks!27.「Cfz Round 2」Binary28.CF1833G29.P1028230.CF1939C31.2024省选OIFC模拟T132.P140733.P10218 魔法手杖34.P165335.取模二题36.CF1699C37.ABC35238.P6627 [省选联考 2020 B 卷] 幸运数字39.P6619 [省选联考 2020 A/B 卷] 冰火战士40.2024PKUSC游记非常有思维的一道题
在遇到计数类dp时,我们首先要找到子问题。然后我们要设计dp状态(这个通常就是当前的计数),然后转移方程要做到不重不漏(这我感觉是最难的地方)。
对于这题,我们先设计出dp方程:dp[i]代表1-i都保留时序列的种类。然后我们可以想到如果i-j能消成只有a[i],a[j],那么dp[i]+=dp[j] (先将后面消成a[i],a[j],然后前面再消,能理解吧?) 因为每个dp[i]的第一位和最后一位都不同。(自己看翻译)。然后这个朴素的dp是的。考虑优化。首先我们考虑优化判定能不能消的过程。我们发现如果两个相邻的数是相同的,那么这两个数必定不会被消掉。考虑将这这些数隔开。那么讨论就简单许多了。前提是相邻数互不相等:
1.只有一种颜色,不符合前提
2.有两种颜色:那么只可能形如 b|abababab|a,这种情况能够全删只可能是 a|b|a。因为只要中间那段长度大于1后,随便删掉哪个数都会变成第1种情况。
3.有三种及以上颜色:那么最坏情况下也肯定形如 a|babacababababcababab|a,我们单独把 c 拿出来,可以发现,我们只要以 c 为中心,不断地消除左边和右边的数,然后遇到另一个c时,留下中间那个再消即可。
区间数的种类在dp的过程中用双指针非常好维护。
然后我们发现这个转移是一段范围的,可以用前缀和优化,就做完了。代码有点细节:
#include<bits/stdc++.h>
using namespace std;
const long long mod=998244353;
long long n,a[200005],b[200005],dp[200005],sum[200005],tot,lst[200005],ans=1;
int main(){
cin>>n;
for(long long i=1;i<=n;i++){
cin>>a[i];
}
long long l=1;
for(long long i=1;i<=n;i++){
if(!b[a[i]]) tot++;
b[a[i]]++;
while(tot>=3&&l<i-2){//第一个限制条件是保证数的种类的,第二个是为了避免和分讨中的第二种情况算重
b[a[l]]--;
if(!b[a[l]]) tot--;
l++;//因为不满足条件后还会++一次,所以下文是sum[lst[i]-1]
}
lst[i]=l;
}
l=1;//当前断开的的段的左端点
dp[0]=1;
for(long long i=1;i<=n;i++){
if(a[i]==a[i-1]) l=i;//断开相邻颜色相同的段
dp[i]=dp[i-1];//如果后面不处理的话就是前面的方案
if(i>=3) if(a[i-1]!=a[i-2]&&a[i-1]!=a[i]) dp[i]=(dp[i]+dp[i-2])%mod;
//如果i-1能消对应分讨中2的a|b|a中的情况,这样也要算上dp[i-2]的贡献,意思是消掉i-1的方案,不消的情况在上一行解决了
if(lst[i]>l) dp[i]=((dp[i]+sum[lst[i]-1])%mod-sum[l-1]+mod)%mod;//对应第二段第一句话
sum[i]=(sum[i-1]+dp[i])%mod;//前缀和优化
}
cout<<dp[n]<<endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· 单线程的Redis速度为什么快?
· 展开说说关于C#中ORM框架的用法!
· Pantheons:用 TypeScript 打造主流大模型对话的一站式集成库
· SQL Server 2025 AI相关能力初探