Atcoder

description

给你\(n\)和\(\{a_i\}\),你需要求所有满足\(p_i\le a_i\)的\(1-n\)排列的逆序对个数之和模\(10^9+7\)。

\(n \le 2\times10^5\)

sol

首先考虑一下所有满足要求的排列总数。记\(cnt_i\)表示有多少个\(a_k\ge i\),从大到小填数,方案数就是$$S=\prod_{i=1}^ncnt_i-(n-i)$$

考虑枚举两个位置\(i,j\),计算满足\(p_i>p_j\)的排列数。分两种情况讨论:

\(a_i\le a_j\):这时候如果你让\(a_j=a_i\)的话方案数也是一样的,所以就强制把\(a_j\)改成\(a_i\),计算满足条件的排列数。因为两个位置本质上没有区别,所以\(p_i>p_j\)的排列数会恰好是合法排列数的一半。而强制把\(a_j\)改小这个操作相当于是把连续一段的\(cnt_i\)减一,可以用某种方式来维护一下。

\(a_i>a_j\):总排列数减不合法,相当于是要求\(p_i<p_j\)的方案数。无非是把上面的\(i,j\)互换了而已,计算方法还是一样的。

考虑一下怎么把\(O(n^2)\)的枚举优化到\(O(n\log n)\)。记\(D_i=\frac{cnt_j-1-(n-j)}{cnt_j-(n-j)}\)。那么枚举一对\(i,j\),它们的贡献是$$S\times\prod_{k=a_i+1}{a_j}D_k=S\times\frac{\prod_{k=1}{a_j}D_k}{\prod_{k=1}^{a_i}D_k}$$

树状数组以\(a_i\)为下标,维护\(\frac{1}{\prod_{k=1}^{a_i}D_k}\)的前缀和即可。

但是这样有问题。因为\(D_i\)可能为\(0\)。我们可以对每个位置,找到它前面出现的第一个\(0\),显然这个\(0\)之前的所有\(i\)都不会有贡献了,而在这个\(0\)之后到\(j\)这一段一定没有\(0\),所以可以维护不含\(0\)的\(D_i\)前缀积。

\(a_i>a_j\)同理,需要额外维护个数以便计算总方案减不合法。

code

#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
int gi(){
int x=0,w=1;char ch=getchar();
while ((ch<'0'||ch>'9')&&ch!='-') ch=getchar();
if (ch=='-') w=0,ch=getchar();
while (ch>='0'&&ch<='9') x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return w?x:-x;
}
const int N = 2e5+5;
const int mod = 1e9+7;
int n,a[N],cnt[N],S=1,z[N],st[N],D[N],ID[N],c1[N],c2[N];
int fastpow(int a,int b){
int res=1;
while (b) {if (b&1) res=1ll*res*a%mod;a=1ll*a*a%mod;b>>=1;}
return res;
}
void mdf(int k,int v){while(k<=n)c1[k]=(c1[k]+v)%mod,++c2[k],k+=k&-k;}
int qry1(int k){int s=0;while(k)s=(s+c1[k])%mod,k^=k&-k;return s;}
int qry2(int k){int s=0;while(k)s+=c2[k],k^=k&-k;return s;}
int main(){
n=gi();
for (int i=1;i<=n;++i) ++cnt[a[i]=gi()];
for (int i=n;i>=1;--i) cnt[i]+=cnt[i+1];
for (int i=1;i<=n;++i){
cnt[i]-=n-i;
if (cnt[i]<=0) return puts("0"),0;
S=1ll*S*cnt[i]%mod;
}
st[0]=D[0]=1;
for (int i=1;i<=n;++i){
int x=1ll*(cnt[i]-1)*fastpow(cnt[i],mod-2)%mod;
if (!x) st[z[i]=z[i-1]+1]=i,D[i]=D[i-1];
else z[i]=z[i-1],D[i]=1ll*D[i-1]*x%mod;
ID[i]=fastpow(D[i],mod-2);
}
int inv2=(mod+1)>>1,ans=0;
for (int i=1;i<=n;++i){
ans=(ans+1ll*(qry1(a[i])-qry1(st[z[a[i]]]-1)+mod)*D[a[i]]%mod*S%mod*inv2)%mod;
mdf(a[i],ID[a[i]]);
}
memset(c1,0,sizeof(c1)),memset(c2,0,sizeof(c2));
for (int i=n;i;--i){
ans=(ans-1ll*(qry1(a[i]-1)-qry1(st[z[a[i]]]-1)+mod)*D[a[i]]%mod*S%mod*inv2%mod+mod)%mod;
ans=(ans+1ll*qry2(a[i]-1)*S)%mod;
mdf(a[i],ID[a[i]]);
}
printf("%d\n",ans);
return 0;
}

[agc23E]Inversions的更多相关文章

  1. [UCSD白板题] Number of Inversions

    Problem Introduction An inversion of a sequence \(a_0,a_1,\cdots,a_{n-1}\) is a pair of indices \(0 ...

  2. Codeforces Round #301 (Div. 2) E . Infinite Inversions 树状数组求逆序数

                                                                    E. Infinite Inversions               ...

  3. Inversions After Shuffle

    Inversions After Shuffle time limit per test 1 second memory limit per test 256 megabytes input stan ...

  4. 《算法导论》Problem 2-4 Inversions

    在Merge Sort的基础上改改就好了. public class Inversions { public static int inversions(int [] A,int p, int r) ...

  5. Dynamic Inversions II 逆序数的性质 树状数组求逆序数

    Dynamic Inversions II Time Limit: 6000/3000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Other ...

  6. Dynamic Inversions 50个树状数组

    Dynamic Inversions Time Limit: 30000/15000MS (Java/Others) Memory Limit: 128000/64000KB (Java/Others ...

  7. [Swift]LeetCode775. 全局倒置与局部倒置 | Global and Local Inversions

    We have some permutation Aof [0, 1, ..., N - 1], where N is the length of A. The number of (global) ...

  8. [LeetCode] Global and Local Inversions 全局与局部的倒置

    We have some permutation A of [0, 1, ..., N - 1], where N is the length of A. The number of (global) ...

  9. 775. Global and Local Inversions

    We have some permutation A of [0, 1, ..., N - 1], where N is the length of A. The number of (global) ...

随机推荐

  1. javascript原生事件总结

    javascript原生的事件,总结了一下,包括事件流.处理函数.事件对象这几样东西.而在兼容性方面,主要是老牌ie8以及以下和现代浏览器的差异,也就是ie和DOM事件标准的差异. 事件流这个事件流i ...

  2. ABP官方文档翻译 0.0 ABP官方文档翻译目录

    一直想学习ABP,但囿于工作比较忙,没有合适的契机,当然最重要的还是自己懒.不知不觉从毕业到参加工作七年了,没留下点儿什么,总感觉很遗憾,所以今天终于卯足劲鼓起勇气开始写博客.有些事能做的很好,但要跟 ...

  3. 【运维技术】slc pm 启动不了,异常排除问题记录

    问题描述 slc pm 启动的时候报错如下: [root@iZuf61qpjpeuqc5mjo4kn8Z lixiang-scf-web]# slc pm strong-remoting deprec ...

  4. imx6------watchdog导致不进系统

    刚上板子,把大部分驱动都停了,不过watchdog的驱动没停,当时想没应用程序所以watchdog不用管,没想到 就是watchdog卡住了,有程序open了watchdog但是没有write,结果t ...

  5. bzoj 4443: [Scoi2015]小凸玩矩阵

    Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 149  Solved: 81[Submit][Status][Discuss] Description ...

  6. java maven 操作 收集的一些命令

    maven打包: mvn clean package -Dmaven.test.skip=true 运行jar: java -jar target/spring-boot-scheduler-1.0. ...

  7. 经典线程同步问题(生产者&消费者)--Java实现

    生产者-消费者(producer-consumer)问题是一个著名的线程同步问题.它描述的是:有一群生产者线程在生产产品,并将这些产品提供给消费者线程去消费. 为使生产者与消费者之间能够并发执行,在两 ...

  8. ipconfig会出现多个IP地址

    一.问题描述 今天调试程序的时候发现电脑有两个IP地址,一时间不知道该用哪个?如下图: 二.问题分析 第一个叫ppp适配器,是一个逻辑的虚拟设备,ppp的意思是Point-to-Point Proto ...

  9. vue双向数据绑定最最最最最简单直观的例子

    vue双向数据绑定最最最最最简单直观的例子 一.总结 一句话总结:双向绑定既不仅model可以影响view的数据,view也可以影响model的数据 view model 数据 1.vue双向数据绑定 ...

  10. 关于UDP很好的书籍和文章(整理、持续更新)

    文章 告知你不为人知的 UDP:疑难杂症和使用(必看)