AT_abc380_g Another Shuffle Window 题解

题目大意:给定 n,k 和一个长度为 n 的排列,问随机选择一个长度为 k 的区间进行随机打乱,排列的逆序对数的期望。

考虑对每一个长度为 k 的区间分别计算答案。先计算随机打乱的这个区间对其他数的贡献,也就是总逆序对数减去原来区间内的逆序对数。这一部分我们在移动区间的时候用树状数组直接计算即可。然后就是区间内部的贡献,一个长为 m 的区间随机打乱之后,对于所有的 m×(m1)2 个二元组,显然都有 12 的概率构成逆序对,因此答案再加上 k×(k1)4 即可。

代码:


#include<bits/stdc++.h>
using namespace std;
inline void rd(){}
template<typename T,typename ...U>
inline void rd(T &x,U &...args){
	char ch=getchar();
	T f=1;x=0;
    while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	x*=f;rd(args...);
}
const int N=2e5+5,mod=998244353;
int n,k,p[N];
inline int KSM(int x,int n){
	int ans=1;
	while(n){
		if(n&1)ans=1ll*x*ans%mod;
		x=1ll*x*x%mod;
		n>>=1;
	}
	return ans;
}
int t[N];
inline void Add(int x,int v){while(x<=n)t[x]+=v,x+=x&-x;}
inline int Query(int x){int ans=0;while(x)ans+=t[x],x-=x&-x;return ans;}
inline void Insert(int x,int &sum){
	(sum+=(Query(n)-Query(x-1)+mod)%mod)%=mod;
	Add(x,1);
}
inline void Delete(int x,int &sum){
	Add(x,-1);
	(sum+=mod-Query(x))%=mod;
}
signed main(){
	rd(n,k);
	for(int i=1;i<=n;i++)rd(p[i]);
	int now=0,ans=0,sum=0;
	for(int i=1;i<=n;i++)Insert(p[i],sum);
	memset(t,0,sizeof t);
	for(int i=1;i<=k;i++)Insert(p[i],now);
	const int INV=KSM(n-k+1,mod-2),SUM=1ll*(k-1)*k%mod*KSM(4,mod-2)%mod;
	for(int i=1;i+k-1<=n;i++){
		(ans+=INV*(0ll+sum-now+SUM+mod)%mod)%=mod;
		if(i+k-1<n){
			Insert(p[i+k],now);
			Delete(p[i],now);
		}
	}printf("%d\n",ans);
	return 0;
}


本文作者:KIreteria

本文链接:https://www.cnblogs.com/11-twentythree/p/18550717

版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。

posted @   KIreteria  阅读(7)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示
评论
收藏
关注
推荐
深色
回顶
收起