专栏文章
CF2069C Beautiful Sequence 解题报告
CF2069C题解参与者 2已保存评论 1
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 1 条
- 当前快照
- 1 份
- 快照标识符
- @miq7etbx
- 此快照首次捕获于
- 2025/12/04 00:11 3 个月前
- 此快照最后确认于
- 2025/12/04 00:11 3 个月前
题目大意
有一个只有 组成的序列 ,找漂亮子序列(对于非首元素,左边都有比它小的元素,非尾元素,右边都有比它大的元素)的个数,答案对 取模。
解题思路
对于只有 组成的序列,不难想出这个漂亮子序列的形式:首元素是 ,尾元素是 ,中间必须全是 。
对于每一个 ,遍历它后面的这个序列时,当它遇到 时,它和这个 对答案的贡献为 ( 为当前 和当前 之间的 的个数)。则这个 对答案的总贡献为
其中 为这个布尔表达式的值。
显然这个式子是需要 的复杂度实现的,如何简化时间复杂度呢?
考虑将第一个 所贡献的答案求出为 ,在遍历时想要在 的基础上进行运算得出后面的 对答案的贡献:
- 用一个 的个数的后缀 代表 后面的 的个数,显然每遇到一个 , 的个数减一;
- 每遇到一个 ,对于这个 后面的每个 ,它对答案的贡献都要从 变为 ,操作为 再 。则遇到这个 ,对 的总变化为 再 。
- 每遇到一个 ,此时的 就是它对答案的变化,直接加到答案上即可。
预处理求出 和 的时间复杂度为 ,遍历序列的复杂度为 ,其中 为模数 。
总时间复杂度 。
AC Code
CPP#include<bits/stdc++.h>
#define int long long
#define mod 998244353
using namespace std;
int n;
int a[200005];
int re()//快读
void wr(int x)//快写
int ksm(int a,int b)//快速幂
{
int ans=1;
for(;b;a*=a,a%=mod,b>>=1)
if(b&1)
ans*=a,ans%=mod;
return ans;
}
signed main(){
int T=re();
while (T--)
{
int n=re(),ans=0;
for(int i=1;i<=n;i++)
a[i]=re();
int cnt2=0,cnt3=0;
int ans1=0,pos=n;//pos为第一个1的位置
for(int i=1;i<=n;i++)
if(a[i]==1)
{
pos=i;
break;
}
for(int i=pos;i<=n;i++)
if(a[i]==2)
cnt2++;
else if(a[i]==3)
{
ans1+=ksm(2,cnt2)-1;//这个3对答案的贡献
ans1%=mod;
cnt3++;
}
ans+=ans1;
for(int i=pos+1;i<=n;i++)
if(a[i]==2)//遇到2
ans1-=cnt3,ans%=mod,ans+=mod,ans%=mod,ans1*=ksm(2,mod-2),ans1%=mod;
else if(a[i]==1)
ans+=ans1,ans%=mod;
else
cnt3--;//遇到3
wr(ans),puts("");
}
return 0;
}
相关推荐
评论
共 1 条评论,欢迎与作者交流。
正在加载评论...