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

题面

BZOJ

洛谷

UOJ

题解

考场推出了就是两个上升子序列,并且最长下降子序列长度不超过\(2\)。。。然后大力暴力状压\(dp\)混了\(44\)分。。。这个结论并不是很难证明,考虑一下冒泡排序的过程就好了。

实际上\(O(n^2)\)并不是很难吧。。。

先不考虑字典序的问题,设\(f[i][j]\)表示长度为\(i\)的\([1,i]\)的排列,并且第一个数为\(j\)的合法排列方案数。

考虑如何转移,如果\(j=1\),那么后面怎么放都行,所以$\displaystyle f[i][1]=\sum_{j=1}^{i-1}f[i-1][j] $。注意一下后面的数所谓的排列我们理解为抛掉第一个数之后,剩下的位置重新离散后的值。

否则不以\(1\)开头,如果下一个数比\(j\)大,那么是没有问题的,这部分就是\(\displaystyle f[i][j]\rightarrow \sum_{k=j}^{i-1}f[i-1][k]\)。

那么如果下一个数比\(j\)小,如果下个数不是\(1\)的话,显然当前\(j\)、下一个数、\(1\),就构成了一个不合法的状态。

实际上想想就是,所有小于当前数的数,也就是\([1,j-1]\)在排列中一定是相对有序的,即强制顺序排列。

那么这样子的方案数是什么呢?\(f[i-1][j-1]\)。

为啥呢?

如果\(j=2\),显然后面接一个\(1\)是没有任何问题的。

否则的话,我们把接在后面的这样子一个合法的排列给弄出来,然后把\(j\)接在开头,显然会出现\(j,j-1,1\)这个不合法的东西,那么我们做个转换,强制令\(j-1\)变成\(1\),然后剩下的\([1,j-2]\)这些数全部加一,不难发现这样子\([1,j-1]\)这些数就被强制顺序排列了。

这样子我们就有转移了:\(\displaystyle f[i][j]=\begin{cases}\sum_{k=1}^{i-1}f[i-1][k]&j=1\\\sum_{k=j-1}^{i-1}f[i-1][k]&j>1\end{cases}\)

好的,我们显然可以\(O(n^2)\)的算出\(f\)数组,考虑怎么计算答案了。

显然是前面一部分卡紧范围,然后从某个特定的位置开始,大于了给定的字典序,然后后面就可以放飞自我了。

假装我们紧紧卡住了\([1,i-1]\)这些位置,然后从\(i\)位置开始放飞自我。

假设有在\(q[i..n]\)中有\(k\)个数要小于\(q[1..i]\)中的前缀最大值。

这里分情况讨论贡献,并且以下讨论都是在前缀合法的情况下进行的。判断当前是否合法只需要维护前缀最大值、前缀次大值以及后缀最小值,实时检查是否合法即可。

显然后面要填进去的数中,大于当前前缀最大值的数是没有任何影响的,而小于前缀最小值的数则强制从小往大填。怎么强制从小往大填呢?显然任何一个以大于前缀最大值开头的填法中,这一段都被强制按照顺序填,显然开头比前缀最大值要大的时候,一定被强制按照顺序填了,所以这一部分的贡献是\(\displaystyle \sum_{j=k+1}^{n-i+1}f[n-i+1][j]\)。

然而发现似乎并没有以没有以比前缀最大值小的数中的最小值为开头的贡献。

的确没有考虑,但是因为这里要限制字典序,所以当前这里填的数必须比前缀最大值大后面才不会受到字典序的限制,所以这里就没有这一部分贡献了。。。

这样子就可以做到\(O(Tn^2)\)的复杂度。

复杂度的瓶颈在于求解\(f\)数组以及其后缀和。

显然不能在通过求解\(f\)再求解其后缀和了,这样子效率太差。

设\(\displaystyle s[n][m]=\sum_{i=m}^n f[n][i]\),即\(f\)的后缀和。

那么有:

\[\begin{aligned}
s[n][m]&=\sum_{i=m}^n f[n][i]\\
&=\sum_{i=m}^n \sum_{j=i-1}^{n-1} f[n-1][j]\\
&=\sum_{j=m-1}^{n-1} f[n-1][j]\sum_{i=m}^{j+1} 1\\
&=\sum_{j=m-1}^{n-1} f[n-1][j]+\sum_{j=m-1}^{n-1} f[n-1][j]\sum_{i=m+1}^{j+1} 1\\
&=s[n-1][m-1]+\sum_{i=m+1}^{n}\sum_{j=i-1}^{n-1}f[n-1][j]\\
&=s[n-1][m-1]+s[n][m+1]
\end{aligned}\]

明摆着找组合意义,走\(n\)步,每次可以向上走一步或者向下走一步,最终停在\(m\)位置,且中途不能走到\(0\)下面去的方案数。

行,那不就是这题??

那么推出来就是\(\displaystyle s[n][m]={2n-m\choose n-m}-{2n-m\choose n-m-1}\)

然后???

然后就做完了啊。。

#include<iostream>
#include<cstdio>
using namespace std;
#define MAX 1200001
#define MOD 998244353
inline int read()
{
int x=0;bool t=false;char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=true,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return t?-x:x;
}
int jc[MAX],jv[MAX],inv[MAX];
int n,q[MAX],mn[MAX],ans;
int c[MAX];
int lb(int x){return x&(-x);}
void add(int x,int w){while(x<=n)c[x]+=w,x+=lb(x);}
int getsum(int x){int s=0;while(x)s+=c[x],x-=lb(x);return s;}
int C(int n,int m){if(m>n)return 0;return 1ll*jc[n]*jv[m]%MOD*jv[n-m]%MOD;}
int S(int n,int m){if(m>n)return 0;return (C(n+n-m,n-m)+MOD-C(n+n-m,n-m-1))%MOD;}
int main()
{
jc[0]=jv[0]=inv[0]=inv[1]=1;
for(int i=1;i<MAX;++i)jc[i]=1ll*jc[i-1]*i%MOD;
for(int i=2;i<MAX;++i)inv[i]=1ll*inv[MOD%i]*(MOD-MOD/i)%MOD;
for(int i=1;i<MAX;++i)jv[i]=1ll*jv[i-1]*inv[i]%MOD;
int T=read();
while(T--)
{
n=read();ans=0;if(!n){puts("0");continue;}
for(int i=1;i<=n;++i)q[i]=read(),c[i]=0;
mn[n]=q[n];for(int i=n-1;i;--i)mn[i]=min(mn[i+1],q[i]);
for(int i=1;i<=n;++i)add(q[i],1);
for(int i=1,mx=0,smx=0;i<=n;++i)
{
if(smx>mn[i])break;
int k=getsum(max(mx,q[i]));add(q[i],-1);
ans=(ans+S(n-i+1,k+1))%MOD;
if(q[i]<mx)smx=max(smx,q[i]);mx=max(mx,q[i]);
}
printf("%d\n",ans);
}
}

【BZOJ5416】【NOI2018】冒泡排序(动态规划)的更多相关文章

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

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

  2. BZOJ_5416_[Noi2018]冒泡排序_DP+组合数+树状数组

    BZOJ_5416_[Noi2018]冒泡排序_DP+组合数+树状数组 Description www.lydsy.com/JudgeOnline/upload/noi2018day1.pdf 好题. ...

  3. 【洛谷4769】[NOI2018] 冒泡排序(动态规划_组合数学)

    题目: 洛谷 4769 博客页面左下角的嘴嘴瓜封神之战中的题目 分析: 一个排列交换次数为 \(\frac{1}{2}\sum_{i=1}^{n}|i-p_i|\) 的充要条件是这个排列不存在长度为 ...

  4. [NOI2018]冒泡排序

    https://www.zybuluo.com/ysner/note/1261482 题面 戳我 \(8pts\ n\leq9\) \(44pts\ n\leq18\) \(ex12pts\ q_i= ...

  5. 【UOJ#394】[NOI2018] 冒泡排序

    题目链接 题意 求有多少个字典序严格大于给定排列 \(q_i\) 的排列满足其逆序对数(冒泡排序需要交换的次数)达到下限 \(\frac{1}{2}\sum_{i=1}^n |i-p_i|\) Sol ...

  6. luogu P4769 [NOI2018]冒泡排序 结论 树状数组 卡特兰数

    LINK:冒泡排序 神题. 可以想到爆搜 期望得分5~10分. 打成这个样子心态不得爆炸? 仔细分析 一个不合法序列还有什么标志. 容易想到某个数字离自己位置相反的方向多走了一步. 考虑单独对每个数字 ...

  7. P4769 [NOI2018]冒泡排序(dp)

    传送门 日常膜拜shadowice巨巨的题解 //minamoto #include<bits/stdc++.h> #define R register #define ll long l ...

  8. NOI2010~NOI2018选做

    [NOI2010] [NOI2010]海拔 高度只需要0/1,所以一个合法方案就是一个割,平面图求最小割. [NOI2010]航空管制 反序拓扑排序,每次取出第一类限制最大的放置,这样做答案不会更劣. ...

  9. Codeforces Round #449 Div. 1

    B:注意到nc/2<=m,于是以c/2为界决定数放在左边还是右边,保证序列满足性质的前提下替换掉一个数使得其更靠近边界即可. #include<iostream> #include& ...

  10. 退役前的最后的做题记录upd:2019.04.04

    考试考到自闭,每天被吊打. 还有几天可能就要AFO了呢... Luogu3602:Koishi Loves Segments 从左向右,每次删除右端点最大的即可. [HEOI2014]南园满地堆轻絮 ...

随机推荐

  1. Django lazy load 懒加载 倒序查询

    Django orm默认懒加载   Django orm默认使用的懒加载,即使用的时候才去访问数据库,且每次默认取最少的数据,当然这样有好处也有坏处... 坏处: 会导致频繁的查询数据库,如涉及到外键 ...

  2. echarts使用笔记四:双Y轴

    1.双Y轴显示数量和占比 app.title = '坐标轴刻度与标签对齐'; option = { title : { //标题 x : 'center', y : 5, text : '数量和占比图 ...

  3. [转帖] SS, SP, BP 三个寄存器

    SS, SP, BP 三个寄存器 https://blog.csdn.net/vspiders/article/details/55669265 这么看 计算机组成原理 还有 考试的很多题目非常有用啊 ...

  4. 剑指offer(1)

    题目: 在一个二维数组中(每个一维数组的长度相同),每一行都按照从左到右递增的顺序排序,每一列都按照从上到下递增的顺序排序.请完成一个函数,输入这样的一个二维数组和一个整数,判断数组中是否含有该整数. ...

  5. python之路--装饰器

    二 .通用装饰器的写法 python里面的动态代理. 存在的意义: 在不破坏原有的函数和原有函数的调用基础上,给函数添加新的功能 def wrapper(fn): # fn是目标函数. def inn ...

  6. 《笔记》Apache2 mod_wsgi的配置

    接手了一台古老的服务器的还使用的是mod_wsgi,所以需要配置一下.其实这里有点怀念,记得当年自己折腾第一个app的时候,还是个什么都不懂的菜鸡.当时用django搜方案的时候,还不知道有uwsgi ...

  7. 莫烦scikit-learn学习自修第三天【通用训练模型】

    1. 代码实战 #!/usr/bin/env python #!_*_ coding:UTF-8 _*_ import numpy as np from sklearn import datasets ...

  8. jdbc一点小笔记

    JDBC的常用接口的步骤, 1使用Driver或者Class.forName()进行注册驱动: 2使用DriverManager进行获取数据库的链接.使用Connection获取语句对象.使用语句对象 ...

  9. scss 转为 less

    tnpm install less-plugin-sass2less -g && sass2less **/*.scss {dir}/{name}.less && rm ...

  10. 循环神经网络RNN及LSTM

    一.循环神经网络RNN RNN综述 https://juejin.im/entry/5b97e36cf265da0aa81be239 RNN中为什么要采用tanh而不是ReLu作为激活函数?  htt ...