UOJ#394. 【NOI2018】冒泡排序
原文链接https://www.cnblogs.com/zhouzhendong/p/UOJ394.html
题解
首先我们发现一个数不能既被往左换又被往右换。也就是说不能有任何一个数左边有比他大的,又被有比他小的。
也就是最长下降子序列长度不超过 2 。
所以我们一定可以找到 2 个上升序列包含所有的数。
于是容易想到 $O(n^2)$ 的 dp:
$dp_{i,j}$ 表示加入了 $i$ 个数,最大值为 $j$ 的情况下,填完的方案数。
那么,如果下一个数小于 $i$ ,那肯定是填小于 $j$ 的第一个,否则就是填一个比 $j$ 更大的值。
我们把这个东西看做括号序列,填一个比 $j$ 大的值就相当于加入若干个左括号,然后再加入一个右括号;填一个比 $j$ 小的数字就相当于加入一个右括号。
这个东西的方案数可以用类似于卡特兰数的公式 $C_i = \binom {2i} {i} - \binom {2i} {i-1}$ 的推导方法来得到。
这个请自行搜索,懒得画图了。
代码
#pragma GCC optimize("Ofast","inline")
#include <bits/stdc++.h>
#define clr(x) memset(x,0,sizeof (x))
#define For(i,a,b) for (int i=a;i<=b;i++)
#define Fod(i,b,a) for (int i=b;i>=a;i--)
#define pb push_back
#define mp make_pair
#define fi first
#define se second
#define _SEED_ ('C'+'L'+'Y'+'A'+'K'+'I'+'O'+'I')
#define outval(x) printf(#x" = %d\n",x)
#define outvec(x) printf("vec "#x" = ");for (auto _v : x)printf("%d ",_v);puts("")
#define outtag(x) puts("----------"#x"----------")
#define outarr(a,L,R) printf(#a"[%d...%d] = ",L,R);\
For(_v2,L,R)printf("%d ",a[_v2]);puts("");
using namespace std;
typedef long long LL;
LL read(){
LL x=0,f=0;
char ch=getchar();
while (!isdigit(ch))
f|=ch=='-',ch=getchar();
while (isdigit(ch))
x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
const int N=1200005,mod=998244353;
void Add(int &x,int y){
if ((x+=y)>=mod)
x-=mod;
}
void Del(int &x,int y){
if ((x-=y)<0)
x+=mod;
}
int Pow(int x,int y){
int ans=1;
for (;y;y>>=1,x=(LL)x*x%mod)
if (y&1)
ans=(LL)ans*x%mod;
return ans;
}
int n;
int Fac[N],Inv[N];
void prework(){
int n=N-1;
for (int i=Fac[0]=1;i<=n;i++)
Fac[i]=(LL)Fac[i-1]*i%mod;
Inv[n]=Pow(Fac[n],mod-2);
Fod(i,n,1)
Inv[i-1]=(LL)Inv[i]*i%mod;
}
int C(int n,int m){
if (m>n||m<0)
return 0;
return (LL)Fac[n]*Inv[m]%mod*Inv[n-m]%mod;
}
int p[N];
int q[N],head,tail;
int pos,vis[N];
int calc(int x,int y){
//from (x,y) to (n,n)
//without crossing line x=y
if (x>n||y>n)
return 0;
assert(x<=y);
int _x=y+1,_y=x-1;
return (C(n-x+n-y,n-x)-C(n-_x+n-_y,n-_x)+mod)%mod;
}
void Main(){
n=read();
For(i,1,n)
p[i]=read();
int ans=0;
clr(vis);
pos=1,head=tail=0;
int Mx=0;
int x=0,y=0;
For(i,1,n){
if (p[i]>Mx){
Mx=p[i];
while (pos<p[i]){
if (!vis[pos]){
q[++tail]=pos;
vis[pos]=1;
y++;
}
pos++;
}
Add(ans,calc(x,y+2));
x++,y++;
}
else {
Add(ans,calc(x,y+1));
if (head>=tail||q[head+1]!=p[i])
break;
head++;
x++;
}
vis[p[i]]=1;
}
cout<<ans<<endl;
}
int main(){
prework();
int T=read();
while (T--)
Main();
return 0;
}
UOJ#394. 【NOI2018】冒泡排序的更多相关文章
- BZOJ_5416_[Noi2018]冒泡排序_DP+组合数+树状数组
BZOJ_5416_[Noi2018]冒泡排序_DP+组合数+树状数组 Description www.lydsy.com/JudgeOnline/upload/noi2018day1.pdf 好题. ...
- 【UOJ#394】[NOI2018] 冒泡排序
题目链接 题意 求有多少个字典序严格大于给定排列 \(q_i\) 的排列满足其逆序对数(冒泡排序需要交换的次数)达到下限 \(\frac{1}{2}\sum_{i=1}^n |i-p_i|\) Sol ...
- [NOI2018]冒泡排序
https://www.zybuluo.com/ysner/note/1261482 题面 戳我 \(8pts\ n\leq9\) \(44pts\ n\leq18\) \(ex12pts\ q_i= ...
- luogu P4769 [NOI2018]冒泡排序 结论 树状数组 卡特兰数
LINK:冒泡排序 神题. 可以想到爆搜 期望得分5~10分. 打成这个样子心态不得爆炸? 仔细分析 一个不合法序列还有什么标志. 容易想到某个数字离自己位置相反的方向多走了一步. 考虑单独对每个数字 ...
- BZOJ5416 NOI2018冒泡排序(动态规划+组合数学)
打表可以发现相当于不存在长度>=3的递减子序列. 考虑枚举在哪一位第一次不卡限制.注意到该位一定会作为前缀最大值.判掉已确定位不合法的情况后,现在的问题即为求长度为i.首位>j的合法排列个 ...
- P4769 [NOI2018]冒泡排序(dp)
传送门 日常膜拜shadowice巨巨的题解 //minamoto #include<bits/stdc++.h> #define R register #define ll long l ...
- 【洛谷4769】[NOI2018] 冒泡排序(动态规划_组合数学)
题目: 洛谷 4769 博客页面左下角的嘴嘴瓜封神之战中的题目 分析: 一个排列交换次数为 \(\frac{1}{2}\sum_{i=1}^{n}|i-p_i|\) 的充要条件是这个排列不存在长度为 ...
- NOI2010~NOI2018选做
[NOI2010] [NOI2010]海拔 高度只需要0/1,所以一个合法方案就是一个割,平面图求最小割. [NOI2010]航空管制 反序拓扑排序,每次取出第一类限制最大的放置,这样做答案不会更劣. ...
- Codeforces Round #449 Div. 1
B:注意到nc/2<=m,于是以c/2为界决定数放在左边还是右边,保证序列满足性质的前提下替换掉一个数使得其更靠近边界即可. #include<iostream> #include& ...
随机推荐
- [Leetcode] 01 Matrix
问题: https://leetcode.com/problems/01-matrix/#/description 基本思路:广度优先遍历,根据所有最短距离为N的格找到所有距离为N+1的格,直到所有的 ...
- C++题目:回文数判断
Determine whether an integer is a palindrome. An integer is a palindrome when it reads the same back ...
- 模拟赛20181016 dp
给出1-n的序列插入一个bst: 给出T组询问,包含n,h分别代表点数为n,高度为h的树,求所有插入顺序的合法方案数,模1e9+7 样例输入 1 2 1 样例输出 2 #include<bit ...
- JSON字符串与Map互转
//一.map转为json字符串 public static String map2jsonstr(Map<String,?> map){ return JSONObject.toJSON ...
- 关于SVN报错 svn: E170013 E125006: contains invalid filesystem format option 'addressing logical'
在使用svn的时候,遇到了这样的一个问题 首先我使用TortoiseSVN 右键创建的repository. 之后用IDEA,配置了1.9.4版本的SVN,去commit访问这个仓库 结果出现了以下的 ...
- raw_input与input
raw_input 不管用户输入的是什么,最后打印的类型都会是str字符串类型 input 会根据用户的输入变换成相应的类型,但是需要注意的是我们用户在输入字符或者字符串的时候,需要给他们加上双引号, ...
- 初识Asp.Net WebApi
using System;using System.Collections.Generic;using System.Linq;using System.Net.Http;using System.T ...
- js的splice方法
splice是js原生处理数组的方法,可以在不改变引用的情况下对数组处理 arrayObject.splice(index,howmany,item1,.....,itemX)参数 描述index 必 ...
- 2019年最受欢迎IMX6系列开发板,资料全开源,助力产品研发不在话下
迅为IMX6开发板: Android4.4系统 Linux + Qt5.7系统 Ubuntu12.04系统 部分真实案例:HMI:3D打印机:医疗设备:工控机:触控一体机:车载终端 板载:4G全网 ...
- SQL server 数据库中插入中文变???格式乱码的问题另一种容易忽略的情况(C#操作dapper)
1.先查查 VS2015 中的XXX.cs页面中编码格式,记事本打开另存一下,编码格式可能是ANSI改为unioncode. (中文前面加N或者改排序规则解决不了的情况有可能是以上原因.)