[AGC023E] Inversions
考虑合法序列的方案数,将
逆序对考虑拆成每两个位置
对于
这个柿子的含义是,我们将
同时对于
我们稍微化简一下最上面的柿子:(下面的一样)
按照
#include<bits/stdc++.h>
using namespace std;
#define N 200005
#define ls u<<1
#define rs u<<1|1
#define p 1000000007
#define ll long long
int n,a[N],b[N],c[N],d[N];
ll tr[N<<2],tag[N<<2],all=1,ans;
inline ll qpow(ll a,int b){ll ans=1;for(;b;b>>=1,a=a*a%p)if(b&1)ans=ans*a%p;return ans;}
inline void pushtag(int u,ll x){tr[u]=tr[u]*x%p,tag[u]=tag[u]*x%p;}
inline void push(int u){if(tag[u]!=1)pushtag(ls,tag[u]),pushtag(rs,tag[u]),tag[u]=1;}
inline void pull(int u){tr[u]=(tr[ls]+tr[rs])%p;}
void build(int u,int l,int r){
tr[u]=0,tag[u]=1;
if(l==r)return;
int m=(l+r)>>1;
build(ls,l,m);build(rs,m+1,r);
}
void upd(int u,int l,int r,int x,ll y){
if(l==r)return tr[u]=y,void();
int m=(l+r)>>1;push(u);
if(m>=x)upd(ls,l,m,x,y);
else upd(rs,m+1,r,x,y);
pull(u);
}
ll qry(int u,int l,int r,int L,int R){
if(L<=l&&r<=R)return tr[u];
int m=(l+r)>>1;push(u);ll ans=0;
if(m>=L)ans=(ans+qry(ls,l,m,L,R))%p;
if(m<R) ans=(ans+qry(rs,m+1,r,L,R))%p;
return ans;
}
int t[N];
inline void add(int x){for(int i=x;i<=n;i+=(i&-i))++t[i];}
inline int ask(int x){int ans=0;for(int i=x;i;i-=(i&-i))ans+=t[i];return ans;}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&a[i]),d[i]=i;
sort(d+1,d+1+n,[](const int x,const int y){return a[x]<a[y];});
for(int i=1;i<=n;i++)b[d[i]]=i,c[i]=a[d[i]];
for(int i=1;i<=n;i++)all=all*(c[i]-i+1)%p;
build(1,1,n);
for(int k=1;k<=n;k++){
int i=d[k];
ans=(ans+qry(1,1,n,1,i)*all%p*qpow(2*(a[i]-b[i]+1),p-2)%p)%p;
ans=(ans+(ask(n)-ask(i))*all%p-qry(1,1,n,i,n)*all%p*qpow(2*(a[i]-b[i]+1),p-2)%p+p)%p;
pushtag(1,(c[k]-k)*qpow(c[k]-k+1,p-2)%p);
upd(1,1,n,i,a[i]-b[i]);
add(i);
}
printf("%lld",ans);
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· Manus爆火,是硬核还是营销?
· 终于写完轮子一部分:tcp代理 了,记录一下
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通