结论:一个序列是好序列当且仅当其不存在长度为3的下降子序列
证明:考虑提示,一个长度为3的下降子序列必然会交换三次,
而这三次带来的收益实际上只有2,因此不合法
同时还可以得到:第i个数,要么是前缀最大值,要么是之前的mex
(即要么让他之前没有比他大的,要么让他之后没有比他小的)
用f[i][j]表示剩余i个数,当前最大值为n-j的填写方案(先不考虑字典序)
根据上述结论,得到递推式:$f[i][j]=\sum_{k=0}^{j}f[i-1][k]$,其中f[0][0]=1
即$f[i][j]=f[i-1][j]+f[i][j-1]$,解得$f[i][j]=c(i+j,j)-c(i+j,j-2)$(构造的方法:发现任意个c(i+j+k1,j+k2)都符合,再把常数配出来即可)
先预处理阶乘及逆元,然后就可以快速计算f了,之后枚举i,并求出:1.i之前与p相同;2.i位置上比p大的好序列个数
设i之前的最大值是x,mex是y,分别考虑填新最大值和k的贡献,有$ans+=f[n-i][n-x]\cdot [p[i]<y\le x]+f[n-i+1][n-\max(x,p[i])-1]$,累计即可

 1 #include<bits/stdc++.h>
2 using namespace std;
3 #define mod 998244353
4 #define N 1200005
5 int t,n,k,x,y,ans,vis[N],fac[N],inv[N];
6 int c(int n,int m){
7 if (m<0)return 0;
8 return 1LL*fac[n]*inv[m]%mod*inv[n-m]%mod;
9 }
10 int f(int n,int m){
11 return (c(n+m,m)-c(n+m,m-1)+mod)%mod;
12 }
13 int main(){
14 fac[0]=inv[0]=inv[1]=1;
15 for(int i=1;i<N-4;i++)fac[i]=1LL*fac[i-1]*i%mod;
16 for(int i=2;i<N-4;i++)inv[i]=1LL*(mod-mod/i)*inv[mod%i]%mod;
17 for(int i=2;i<N-4;i++)inv[i]=1LL*inv[i-1]*inv[i]%mod;
18 scanf("%d",&t);
19 while (t--){
20 scanf("%d",&n);
21 x=ans=0;
22 y=1;
23 for(int i=1;i<=n+1;i++)vis[i]=0;
24 for(int i=1;i<=n;i++){
25 scanf("%d",&k);
26 if ((k<y)&&(y<=x))ans=(ans+f(n-i,n-x))%mod;
27 x=max(x,k);
28 if (x<n)ans=(ans+f(n-i+1,n-x-1))%mod;
29 if ((k!=x)&&(k!=y)){
30 for(i++;i<=n;i++)scanf("%*d");
31 break;
32 }
33 vis[k]=1;
34 while (vis[y])y++;
35 }
36 printf("%d\n",ans);
37 }
38 }

[bzoj5416]冒泡排序的更多相关文章

  1. 【BZOJ5416】【NOI2018】冒泡排序(动态规划)

    [BZOJ5416][NOI2018]冒泡排序(动态规划) 题面 BZOJ 洛谷 UOJ 题解 考场推出了就是两个上升子序列,并且最长下降子序列长度不超过\(2\)...然后大力暴力状压\(dp\)混 ...

  2. BZOJ5416 NOI2018冒泡排序(动态规划+组合数学)

    打表可以发现相当于不存在长度>=3的递减子序列. 考虑枚举在哪一位第一次不卡限制.注意到该位一定会作为前缀最大值.判掉已确定位不合法的情况后,现在的问题即为求长度为i.首位>j的合法排列个 ...

  3. [C#][算法] 用菜鸟的思维学习算法 -- 马桶排序、冒泡排序和快速排序

    用菜鸟的思维学习算法 -- 马桶排序.冒泡排序和快速排序 [博主]反骨仔 [来源]http://www.cnblogs.com/liqingwen/p/4994261.html  目录 马桶排序(令人 ...

  4. 算法与数据结构(十三) 冒泡排序、插入排序、希尔排序、选择排序(Swift3.0版)

    本篇博客中的代码实现依然采用Swift3.0来实现.在前几篇博客连续的介绍了关于查找的相关内容, 大约包括线性数据结构的顺序查找.折半查找.插值查找.Fibonacci查找,还包括数结构的二叉排序树以 ...

  5. Html5 冒泡排序演示

    冒泡排序(Bubble Sort),是一种计算机科学领域的较简单的排序算法. 它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来.走访数列的工作是重复地进行直到没有再需要 ...

  6. javascript冒泡排序

    数组冒泡排序算法(升序) 升序:小数在前,大数在后 冒泡排序的原则:每次比较相邻两个元素,如果前一个数>后一个数,说明违反升序的要求,就将两数交换位置.否则,保持不变.继续比较下一对. 例如:玩 ...

  7. Java中的经典算法之冒泡排序(Bubble Sort)

    Java中的经典算法之冒泡排序(Bubble Sort) 神话丿小王子的博客主页 原理:比较两个相邻的元素,将值大的元素交换至右端. 思路:依次比较相邻的两个数,将小数放在前面,大数放在后面.即在第一 ...

  8. C#冒泡排序算法

    用了两种形式的数据,一个是泛型List,一个是数据int[].记录一下,作为自己学习过程中的笔记. using System; using System.Collections.Generic; us ...

  9. python排序之二冒泡排序法

    python排序之二冒泡排序法 如果你理解之前的插入排序法那冒泡排序法就很容易理解,冒泡排序是两个两个以向后位移的方式比较大小在互换的过程好了不多了先上代码吧如下: 首先还是一个无序列表lis,老规矩 ...

随机推荐

  1. Lamport时间戳论文笔记

    本文主要参考文献[1]完成. 声明:本人仅在博客园发表了本文章,笔名LightningStar,其他网站均为转载. 笔记 私以为,论文中作者的核心工作是为分布式系统建立了一种数学模型,并基于这种数学模 ...

  2. The Data Way Vol.2 | 做个『单纯』的程序员还真不简单

    关于「The Data Way」 「The Data Way」是由 SphereEx 公司出品的一档播客节目.这里有开源.数据.技术的故事,同时我们关注开发者的工作日常,也讨论开发者的生活日常:我们聚 ...

  3. 创建线程的4种方法 and 线程的生命周期

    线程的启动和运行 方法一:使用start()方法:用来启动一个线程,当调用start方法后,JVM会开启一个新线程执行用户定义的线程代码逻辑. 方法二:使用run()方法:作为线程代码逻辑的入口方法. ...

  4. C# 三种方式实现Socket数据接收(经典)

    Stream.Read 方法 当在派生类中重写时,从当前流读取字节序列,并将此流中的位置提升读取的字节数. 语法: public abstract int Read(byte[] buffer, in ...

  5. 【数据结构与算法Python版学习笔记】图——词梯问题 广度优先搜索 BFS

    词梯Word Ladder问题 要求是相邻两个单词之间差异只能是1个字母,如FOOL变SAGE: FOOL >> POOL >> POLL >> POLE > ...

  6. kviy TextInput 触发事件

    from kivy.uix.widget import Widget from kivy.app import App from kivy.lang import Builder Builder.lo ...

  7. Git: 搭建一个本地私人仓库

    Git: 搭建一个本地私人仓库 寝室放个电脑.实验室也有个电脑 为进行数据同步,充分利用实验室的服务器搭建了个本地私人仓库 1. 安装流程 当然首先保证服务器上与PC机上都已经安装了可用的Git 在P ...

  8. [软工顶级理解组] Alpha阶段团队贡献分评分

    评分总表 下述表格适用于前端.后端.爬虫开发者的评分,基础分数为50分,在此基础上进行增减. 类别 程度 加减分 准时性 提前完成 +0 按时完成 +0 延后完成,迟交时间一天内或未延误进度 -2 延 ...

  9. numpy.zeros()的作用和实操

    numpy.zeros()的作用: 通常是把数组转换成想要的矩阵 numpy.zeros()的使用方法: zeros(shape, dtype=float, order='C') shape:数据尺寸 ...

  10. 第34篇-解析invokeinterface字节码指令

    与invokevirtual指令类似,当没有对目标方法进行解析时,需要调用LinkResolver::resolve_invoke()函数进行解析,这个函数会调用其它一些函数完成方法的解析,如下图所示 ...