P4769-[NOI2018]冒泡排序【组合数学,树状数组】

1|0正题

题目链接:https://www.luogu.com.cn/problem/P4769


1|1题目大意

有一个冒泡排序的算法

输入:一个长度为 n 的排列 p[1...n] 输出:p 排序后的结果。 for i = 1 to n do for j = 1 to n - 1 do if(p[j] > p[j + 1]) 交换 p[j] 与 p[j + 1] 的值

然后给出一个排列a,求在所有字典序大于a的排列p中冒泡排序交换次数恰好为i=1n|ipi|的排列数。

1n6×105,n2×106


1|2解题思路

打一下表发现合法的排列条件是最长下降子序列不超过2

然后我们先不考虑字典序限制条件怎么做,我们设fi,1/2表示目前下降子序列长度为1/2中末尾最大的那个。

那么fi,1就是目前出现的数中最大的,然后如果我们从前往后填数,那么如果fi,2的数中有没有填进去的,肯定不合法,所以fi,2肯定比目前没有填进去的数中所有数字都小,不需要考虑。

gi,j表示目前还剩下i个数没填,其中fi,1大于其中的j个数,那么有gi,j可以转移到gi1,j1(填在最底)和gi1,k(kj)(填在j上面)。

我们考虑快速的求出每个g,反过来就是gi,j转移到gi+1,j+1gi+1,j

我们维护一个hi,j=gi,ij,那么每次的转移就是hi,j转移到hi,k(jki)

这个转移很像卡特兰数的要求,每次可以往下或者往右,但是不能超过对角线。

这样来说移动到位置(n,m)(mn)的话方案数就是(n+mm)(n+mm1)

然后就是枚举第一个超过该字典序的位置,这样前面的方案固定,剩下的数可以用树状数组计算得出,再用组合数求答案即可。

时间复杂度:O(nlogn)


1|3code

#include<cstdio> #include<cstring> #include<algorithm> #define ll long long #define lowbit(x) (x&-x) using namespace std; const ll N=6e5*2,P=998244353; ll T,n,t[N],a[N],fac[N],inv[N],ans; ll C(ll n,ll m) {if(m<0)return 0;return fac[n]*inv[m]%P*inv[n-m]%P;} void Change(ll x,ll val){ while(x<=n){ t[x]+=val; x+=lowbit(x); } return; } ll Ask(ll x){ ll ans=0; while(x){ ans+=t[x]; x-=lowbit(x); } return ans; } ll F(ll n,ll m){ m=n-1-m;if(!m)return 0;m--; return (C(n+m,m)-C(n+m,m-1)+P)%P; } signed main() { // freopen("inverse3.in","r",stdin); fac[0]=inv[0]=inv[1]=1; for(ll i=2;i<N;i++)inv[i]=P-inv[P%i]*(P/i)%P; for(ll i=1;i<N;i++)fac[i]=fac[i-1]*i%P,inv[i]=inv[i-1]*inv[i]%P; scanf("%lld",&T); while(T--){ scanf("%lld",&n);ans=0; for(ll i=1;i<=n;i++) scanf("%lld",&a[i]),Change(a[i],1); for(ll i=1,mx=0;i<=n;i++){ Change(a[i],-1);mx=max(mx,a[i]); (ans+=F(n-i+1,Ask(mx)))%=P; if(a[i]<mx&&Ask(a[i])) break; } for(int i=1;i<=n;i++)t[i]=0; printf("%lld\n",ans); } return 0; }

__EOF__

本文作者QuantAsk
本文链接https://www.cnblogs.com/QuantAsk/p/16420269.html
关于博主:退役OIer,GD划水选手
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
声援博主:如果您觉得文章对您有帮助,可以点击文章右下角推荐一下。您的鼓励是博主的最大动力!
posted @   QuantAsk  阅读(34)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 被坑几百块钱后,我竟然真的恢复了删除的微信聊天记录!
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 【自荐】一款简洁、开源的在线白板工具 Drawnix
· 园子的第一款AI主题卫衣上架——"HELLO! HOW CAN I ASSIST YOU TODAY
· Docker 太简单,K8s 太复杂?w7panel 让容器管理更轻松!
历史上的今天:
2021-06-28 P3964-[TJOI2013]松鼠聚会【计算几何】
2021-06-28 AT2667-[AGC017D]Game on Tree【SG函数】
2021-06-28 P5163-WD与地图【tarjan,整体二分,线段树合并】
点击右上角即可分享
微信分享提示