LINK:冒泡排序

神题。

可以想到爆搜 期望得分5~10分。

打成这个样子心态不得爆炸?

仔细分析 一个不合法序列还有什么标志.

容易想到某个数字离自己位置相反的方向多走了一步.

考虑单独对每个数字进行分析 每次都是这个数字前面的数字会让它多走一步.

对于每个位置 i 位置上的数字 \(a_i\) \(cnt_i\)表示前面有多少个数字比其大。

那么有 \(i-cnt_i<a_i\)那么就不合法了。

考虑状压 对于字典序可以利用总方案-<=的方案来做 类似数位dp。

期望得分44.

code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 10000000000000000ll
#define inf 1000000000
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(RE int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define fep(n,p,i) for(RE int i=n;i>=p;--i)
#define vep(p,n,i) for(RE int i=p;i<n;++i)
#define pii pair<int,int>
#define mk make_pair
#define RE register
#define P 1000000007ll
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-10
#define sq sqrt
#define S second
#define F first
#define mod 998244353
using namespace std;
char *fs,*ft,buf[1<<15];
inline char gc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
RE int x=0,f=1;RE char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
return x*f; }
const int MAXN=18,maxn=600010;
int n,T;
int a[maxn];
int f[1<<MAXN],c[1<<MAXN];
int g[1<<MAXN][2];
int maxx;
inline void add(int &x,int y){x=x+y>=mod?x+y-mod:x+y;}
int main()
{
//freopen("1.in","r",stdin);
get(T);
int ww=1<<18;
vep(1,ww,i)c[i]=c[i>>1]+(i&1);
while(T--)
{
get(n);
rep(1,n,i)get(a[i]);
if(n<=18)
{
rep(0,maxx,i)f[i]=g[i][0]=g[i][1]=0;
maxx=1<<n;--maxx;
f[0]=1;g[0][1]=1;
rep(0,maxx-1,i)
{
if(!f[i])continue;
int cnt=0;
fep(n,1,j)
{
if(i&(1<<(j-1))){++cnt;continue;}
int s=i|(1<<(j-1));
if(cnt&&c[s]-cnt<j)continue;
add(f[s],f[i]);
add(g[s][0],g[i][0]);
if(j>a[c[s]])continue;
if(j==a[c[s]])add(g[s][1],g[i][1]);
else add(g[s][0],g[i][1]);
}
}
//put(g[1][1]);
put((f[maxx]-g[maxx][0]-g[maxx][1]+mod)%mod);
}
}
return 0;
}

我以为想到这个地方就在第5层了 可是正解大概在第37层.

进一步规约发现的性质。

会出现不合法的情况 一个是前面比其数字多的数字已经让他跑到超过自己位置了。

考虑恰好到其位置的时候 前面还有比其大的数字那么后面一定还存在一个比其小的数字。

那么 由于后面的数字一直存在 那么一开始就是那个局面 一堆比x大的在x前面 后面还有一个比x要小的。

此时可以想到x也会跑到后面去更新比它小的数字 那么前面的数字在让x一直往前的之后 x的位置一定是<x的。

不然x是不会跑到后面更新那个比它小的数字而且更新完后自己还没有办法回到原位.

但是这个条件是前面至少有一个比x大 然后越过x的位置 可以看成后面存在一个<x的数字。

这样 规律就被直接推出来了 即不存在长度为3的下降子序列。

推出来就不需要证明了。

尽管过程略显生硬 但是非常符合逻辑

接下来需要dp了。

先不管字典序。

那么dp出所有合法的序列也是一件困难的事情。

还是由\(i\)推\(i+1\) 考虑第一位放什么。

假设放x 那么比x大的还是可以随便放第二位的 但是比x要小的话需要1~x-1要整齐出现.

此时容易想到 设\(f_{i,j}\)表示长度为i 以j开头的方案数.

那么有 \(f_{i,j}=\sum_{l=max(1,j-1)}^{i-1}f_{i-1,l}\)

这样就可以\(n^2\)递推了.

考虑如何求答案.

欲知后事如何 且听下回分解

update 7.26 继续营业:

没有限制答案就是\(\sum_{i=1}^nf_{n,i}\)

由于答案要求严格比某个排列字典序要大.

我们之所以求这个数组就是为了比较方便的得到答案.

和答案一一比较字典序.到了第i个位置我们要求的是前i-1个位置上的数字相同.

那么当前位置要填x 显然\(x>a_i\) 为了满足要求x还要大于前缀最大值.

为了证明后者 先分类讨论一波 如果前缀最大值\(>a_i\) 那么\(x<\)前缀最大值.

此时放x 后面肯定存在一个\(a_i\)一定是不合法的.

如果前缀最大值等于\(a_i\)显然x要大于\(a_i\) 所以x还是要大于前缀最大值.

我们就可以得到哪些能用数字的集合 \(mx_i+1~n\) 其中\(mx_i\)为\(max_{j=1}^ia_i\)

同时 此时能用的数字个数为n-i+1 这些数字排名也就有了 累加f数值即可.即:

\(\sum_{j=n-i+1-n+mx_i+1}^{n-i+1}f_{n-i+1,j}\)

这样就有一个\(n^2\)的做法了.

期望得分80

code
//#include<bits/stdc++.h>
#include<iostream>
#include<cstdio>
#include<ctime>
#include<cctype>
#include<queue>
#include<deque>
#include<stack>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cstring>
#include<string>
#include<ctime>
#include<cmath>
#include<cctype>
#include<cstdlib>
#include<queue>
#include<deque>
#include<stack>
#include<vector>
#include<algorithm>
#include<utility>
#include<bitset>
#include<set>
#include<map>
#define ll long long
#define db double
#define INF 1000000000
#define inf 1000000000
#define ldb long double
#define pb push_back
#define put_(x) printf("%d ",x);
#define get(x) x=read()
#define gt(x) scanf("%d",&x)
#define gi(x) scanf("%lf",&x)
#define put(x) printf("%d\n",x)
#define putl(x) printf("%lld\n",x)
#define rep(p,n,i) for(RE int i=p;i<=n;++i)
#define go(x) for(int i=lin[x],tn=ver[i];i;tn=ver[i=nex[i]])
#define fep(n,p,i) for(RE int i=n;i>=p;--i)
#define vep(p,n,i) for(RE int i=p;i<n;++i)
#define pii pair<int,int>
#define mk make_pair
#define RE register
#define P 1000000007ll
#define gf(x) scanf("%lf",&x)
#define pf(x) ((x)*(x))
#define uint unsigned long long
#define ui unsigned
#define EPS 1e-10
#define sq sqrt
#define S second
#define F first
#define mod 998244353
#define len(x) t[x].len
#define f(x) t[x].fa
using namespace std;
char *fs,*ft,buf[1<<15];
inline char gc()
{
return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;
}
inline int read()
{
RE int x=0,f=1;RE char ch=gc();
while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=gc();}
while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=gc();}
return x*f; }
const int MAXN=1010;
int n,T;
int f[MAXN][MAXN];
int a[MAXN],mn[MAXN];
inline void add(int &x,int y){x=x+y>=mod?x+y-mod:x+y;}
inline int mus(int x,int y){return x-y<0?x-y+mod:x-y;}
int main()
{
//freopen("1.in","r",stdin);
get(T);n=1000;
f[1][1]=1;
rep(2,n,i)
{
int sum=0;
rep(1,i-1,j)add(sum,f[i-1][j]);
f[i][1]=f[i][2]=sum;
rep(3,i,j)
{
sum=mus(sum,f[i-1][j-2]);
f[i][j]=sum;
}
}
while(T--)
{
get(n);int ans=0;
rep(1,n,i)get(a[i]);
mn[n]=a[n];fep(n-1,1,i)mn[i]=min(a[i],mn[i+1]);
int mx=0,cmx=0;
rep(1,n,i)
{
if(cmx>mn[i])break;
if(mx>a[i])cmx=max(cmx,a[i]);
mx=max(mx,a[i]);
rep(n-i+1-n+mx+1,n-i+1,j)add(ans,f[n-i+1][j]);
}
put(ans);
}
return 0;
}

不管是f数组还是f数组的后缀和 这都是\(n^2\)的.

考虑优化.

欲知后事如何 请听下回分解

luogu P4769 [NOI2018]冒泡排序 结论 树状数组 卡特兰数的更多相关文章

  1. [luogu]P2657低头一族[树状数组]

    [luogu]P2657 低头一族 题目描述 一群青年人排成一队,用手机互相聊天. 每个人的手机有一个信号接收指标,第i个人的接收指标设为v[i]. 如果位置在x[i]的人要和位置在xj的人聊天,那么 ...

  2. Luogu P3374 【模板】树状数组 1

    真正的模板题. 树状数组的思想很简单(不如说背代码更简单),每个节点记录多个节点的信息(每个点存x&(-x)个). 道理可以参见很多大佬的博客,最后前缀和的思想搞一下就好了.不想说也不会说. ...

  3. Luogu P4901 排队 fib数列+树状数组+倍增

    这题让我升华..还好只重构了一遍 首先我们发现:$n$较小时,整个队伍的形态 跟 $n$ 比较大时的局部是一样的 所以我们预处理出这个队伍的形态,和每一行每个位置的质因子个数的前缀和,$O(nlogn ...

  4. 【Luogu】P2617Dynamic Ranking(树状数组套主席树)

    题目链接 树状数组套主席树有点难懂qwq 不好理解 树状数组套主席树的直观理解应该是:树状数组的每一个节点是一棵主席树. 普通区间修改我们是创建1个线段树,树状数组套主席树的时候我们就创建log个线段 ...

  5. 题解报告:Luogu P3368 【模板】树状数组 2(区间修改,单点查询)

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...

  6. 4.9 省选模拟赛 划分序列 二分 结论 树状数组优化dp

    显然发现可以二分. 对于n<=100暴力dp f[i][j]表示前i个数分成j段对于当前的答案是否可行. 可以发现这个dp是可以被优化的 sum[i]-sum[j]<=mid sum[i] ...

  7. 树状数组例题-数星星,简单题easy,校门外的树2,清点人数

    [例1]数星星 天空中有一些星星,这些星星都在不同的位置,每个星星都有个坐标,如果一个星星的左下方(包括正左和正下)有k颗星星,就说这颗星星是k级的. 比如,上图中,星星5是3级的(1,2,4在其左下 ...

  8. luogu P3368 【模板】树状数组 2

    题目描述 如题,已知一个数列,你需要进行下面两种操作: 1.将某区间每一个数数加上x 2.求出某一个数的和 输入输出格式 输入格式: 第一行包含两个整数N.M,分别表示该数列数字的个数和操作的总个数. ...

  9. luogu P2345 奶牛集会 |排序+树状数组

    题目描述 约翰的N 头奶牛每年都会参加"哞哞大会".哞哞大会是奶牛界的盛事.集会上的活动很多,比如堆干草,跨栅栏,摸牛仔的屁股等等.它们参加活动时会聚在一起,第i 头奶牛的坐标为X ...

随机推荐

  1. h5移动端实现图片文件上传

    PC端上传文件多半用插件,引入flash都没关系,但是移动端要是还用各种冗余的插件估计得被喷死,项目里面需要做图片上传的功能,既然H5已经有相关的接口且兼容性良好,当然优先考虑用H5来实现. JS代码 ...

  2. Codeforces 1215D Ticket Game 题解

    Codeforces 1215D Ticket Game 原题 题目 Monocarp and Bicarp live in Berland, where every bus ticket consi ...

  3. Face The Right Way思维。。。

    题目再次链接 题意: 已知01序列a,求进行定长子串取反的最少操作次数,以及最少时的定长. 分析: 首先,先想一想怎么暴力吧.这样想:要保证最小,那么必然不会对同一个区间反转两次,而在k一定时,则不会 ...

  4. Mysql如何取当日的数据

    下面的sql语句可以取出当日的数据 SELECT * FROM table WHERE 时间字段 BETWEEN DATE_FORMAT(NOW(),'%Y-%m-%d 00:00:00') AND ...

  5. Python——格式化GMT时间

    1.背景 最近在做视频上传去获取大小.时间的功能,视频是存在金山云的,由于金山sdk接口用例执行后返回的结果中的时间是http头部时间,时间格式为‘Tue, 08 May 2018 06:17:00 ...

  6. 如何查询到你的wifi所在的公网ip?

    浏览器中输入:ip138.com  即可查询到.

  7. Disruptor 高性能并发框架二次封装

    Disruptor是一款java高性能无锁并发处理框架.和JDK中的BlockingQueue有相似处,但是它的处理速度非常快!!!号称“一个线程一秒钟可以处理600W个订单”(反正渣渣电脑是没体会到 ...

  8. JVM 学习笔记(三)

    一:使用jvisualvm工具查看堆内存 visualgc插件下载链接 : https://visualvm.github.io/pluginscenters.html --->选择对应版本链接 ...

  9. flask 源码专题(四):wtforms Form实例化流程以及csrf验证

    class LoginForm(Form): #首先执行后得到的结果是UnboundField()对象 name=simple.StringField( label='用户名', validators ...

  10. JavaScript动画实例:沿五角星形线摆动的小圆

    五角星形线的笛卡尔坐标方程式可设为: r=10+(3*sin(θ*2.5))^2  x=r*cos(θ) y=r*sin(θ)              (0≤θ≤2π) 根据这个曲线方程,在[0,2 ...