Description

给出长度为 \(n\) 序列 \(A_i\),求出所有长度为 \(n\) 的排列 \(P\),满足 \(P_i<=A_i\),求所有满足条件的 \(P\) 的逆序对数之和

题面

Solution

设 \(c[k]\) 表示 \(A_i>=k\) 的个数,那么对于所有的 \(c[k]>=(n-k+1)\),不满足则不合法

把 \(c[k]\) 变为 \(c[k]-(n-k),\)总方案就是 \(\Pi c[k]\)

考虑逆序对 \((i,j)\) 的贡献

如果满足 \(A_i<=A_j\) ,那么把 \(A_j\) 变成 \(A_i\),然后 \((i,j)\) 作为逆序对的方案数就是合法排列的方案数除以 \(2\)

把 \(A_j\) 变成 \(A_i\) 之后,\([A_i+1,A_j]\) 这一个区间的 \(c\) 会减 \(1\),可以维护一个前缀积 \(\frac{c_i-1}{c_i}\) 可以 \(O(1)\) 算出替换后的贡献

那么就可以树状数组维护一下每个数对的贡献了

对于 \(A[i]>A[j]\) 的情况,补集转换一下,总方案-把 \(A_i\) 替换成 \(A_j\) 的方案,然后和上面一样的做一遍就好了

#include<bits/stdc++.h>
using namespace std;
template<class T>void gi(T &x){
int f;char c;
for(f=1,c=getchar();c<'0'||c>'9';c=getchar())if(c=='-')f=-1;
for(x=0;c<='9'&&c>='0';c=getchar())x=x*10+(c&15);x*=f;
} const int N=2e5+10,mod=1e9+7;
inline int qm(int x,int k){
int sum=1;
while(k){
if(k&1)sum=1ll*sum*x%mod;
x=1ll*x*x%mod;k>>=1;
}
return sum;
}
int n,a[N],c[N],v0[N],R[N],tr[N],S;
inline void add(int x,int t){
for(int i=x;i<=n;i+=(i&(-i)))tr[i]=(tr[i]+t)%mod;
}
inline int qry(int x){
int ret=0;
for(int i=x;i>=1;i-=(i&(-i)))ret=(ret+tr[i])%mod;
return ret;
}
int main(){
freopen("pp.in","r",stdin);
freopen("pp.out","w",stdout);
cin>>n;
for(int i=1;i<=n;i++)gi(a[i]),c[a[i]]++;
for(int i=n-1;i>=1;i--)c[i]+=c[i+1]-1;
for(int i=1;i<=n;i++)if(c[i]<=0)return puts("0"),0;
v0[0]=S=1;
for(int i=1;i<=n;i++){
v0[i]=1ll*v0[i-1]*(c[i]>1?c[i]-1:1)%mod*qm(c[i],mod-2)%mod;
S=1ll*S*c[i]%mod;
}
R[n]=n;
for(int i=n-1;i>=1;i--)R[i]=c[i+1]>1?R[i+1]:i;
int ans=0,t;
//A[i]<=A[j]
for(int i=n;i>=1;i--){
t=(qry(R[a[i]])-qry(a[i]-1)+mod)%mod;
ans=(ans+1ll*t*qm(v0[a[i]],mod-2))%mod;
add(a[i],v0[a[i]]);
}
//A[i]>A[j]
R[1]=1;
memset(tr,0,sizeof(tr));
for(int i=2;i<=n;i++)R[i]=c[i]>1?R[i-1]:i;
for(int i=n;i>=1;i--){
t=(qry(a[i]-1)-qry(R[a[i]]-1)+mod)%mod;
ans=(ans-1ll*t*v0[a[i]]%mod+mod)%mod;
add(a[i],qm(v0[a[i]],mod-2));
}
ans=1ll*ans*qm(2,mod-2)%mod;
memset(tr,0,sizeof(tr));
for(int i=1;i<=n;i++){
ans=(1ll*ans+i-1-qry(a[i])+mod)%mod;
add(a[i],1);
}
ans=1ll*ans*S%mod;
cout<<ans<<endl;
return 0;
}

AtCoder Grand Contest 023 E - Inversions的更多相关文章

  1. Atcoder Grand Contest 023 E - Inversions(线段树+扫描线)

    洛谷题面传送门 & Atcoder 题面传送门 毒瘤 jxd 作业-- 首先我们不能直接对所有排列计算贡献对吧,这样复杂度肯定吃不消,因此我们考虑对每两个位置 \(x,y(x<y)\), ...

  2. AtCoder Grand Contest 023 A - Zero-Sum Ranges

    Time limit : 2sec / Memory limit : 256MB Score : 200 points Problem Statement We have an integer seq ...

  3. AtCoder Grand Contest 023 C - Painting Machines

    Description 一个长度为 \(n\) 的序列,初始都为 \(0\),你需要求出一个长度为 \(n-1\) 的排列 \(P\), 按照 \(1\) 到 \(n\) 的顺序,每次把 \(P_i\ ...

  4. AtCoder Grand Contest 023 F - 01 on Tree

    Description 题面 Solution HNOI-day2-t2 复制上去,删点东西,即可 \(AC\) #include<bits/stdc++.h> using namespa ...

  5. Atcoder Grand Contest 023

    A 略 B 略 C(计数) 题意: 有n个白球排成一行,故有n-1个空隙,我可以给一个空隙对应的两个白球都涂黑.n-1个空隙的一个排列就对应着一个涂黑顺序,定义这个涂黑顺序的价值是“将所有n个球都涂黑 ...

  6. AtCoder Grand Contest 012

    AtCoder Grand Contest 012 A - AtCoder Group Contest 翻译 有\(3n\)个人,每一个人有一个强大值(看我的假翻译),每三个人可以分成一组,一组的强大 ...

  7. AtCoder Grand Contest 011

    AtCoder Grand Contest 011 upd:这篇咕了好久,前面几题是三周以前写的... AtCoder Grand Contest 011 A - Airport Bus 翻译 有\( ...

  8. AtCoder Grand Contest 031 简要题解

    AtCoder Grand Contest 031 Atcoder A - Colorful Subsequence description 求\(s\)中本质不同子序列的个数模\(10^9+7\). ...

  9. AtCoder Grand Contest 010

    AtCoder Grand Contest 010 A - Addition 翻译 黑板上写了\(n\)个正整数,每次会擦去两个奇偶性相同的数,然后把他们的和写会到黑板上,问最终能否只剩下一个数. 题 ...

随机推荐

  1. SpringMVC+Hibernate 项目开发之一(Maven环境搭建)

    Maven环境搭建网上一大堆文章,直接引用leiOOlei同学的了:http://www.cnblogs.com/leiOOlei/p/3359561.html Maven版本:apache-mave ...

  2. 内联函数背景、例子、与普通函数的区别及要注意的地方 ------新标准c++程序设计

    背景: 使用函数能够避免将相同代码重些多次的烦恼,还能减少可执行程序的体积,但也会带来程序运行时间上的开销.函数调用在执行时,首先在栈中为形参和局部变量分配存储空间,然后还要将实参的值复制给形参,接下 ...

  3. CI框架集成Smarty

    1.下载smarty源码包,解压放置于项目目录 libriaries中 2.在libraries中建立Cismarty.php ,填写如下代码 <?php if(!defined('BASEPA ...

  4. spring boot日志及Log4j日志配置

    1.默认实现的日志配置 Spring boot默认已经集成了logging,同时也是默认开启的,如果想根据自己的需求对日志进行配置,方法很简单--只需要在配置文件中进行相应设置,这里提供我自己的配置如 ...

  5. win7系统电脑显示windows副本不是正版怎么办

    win7系统电脑显示windows副本,可以:在开始输入框中输入cmd——以管理员权限运行——在命令行中输入SLMGR -REARM,——重启.

  6. 利用keytool工具生成数字证书

    一.制作数字证书  因测试微信小程序, 腾讯要求使用 https协议,所以需要使用证书.使用jdk工具制作数字证书流程如下: 1.查看JDK是否安装,使用命令java -version 2.切换目录至 ...

  7. 【bzoj4836】二元运算 分治FFT

    Description 定义二元运算 opt 满足 现在给定一个长为 n 的数列 a 和一个长为 m 的数列 b ,接下来有 q 次询问.每次询问给定一个数字 c 你需要求出有多少对 (i, j) 使 ...

  8. dubbo源码分析--dubbo spi解析

    1. 什么叫SPI? 简单总结就是一种使用类名字符串来动态实例化java类的方式,也就是反射. 2. java SPI与Dubbo SPI有什么区别 (此图来自网上,我没有刻意去截图) 然后在这个文件 ...

  9. samba服务器架设

    #samba服务器架设方便线上linux服务器和windows服务器之间共享 1.关闭防火墙service iptables stop 2.关闭SELinuxsetenforce 0 3.安装samb ...

  10. 【FAQ】服务下线

    原因:磁盘已满