题目要我们求
1324−1243−1432
=(1x2x−1423)−(12xx−1234)−(14xx−1423)
=1x2x−12xx+1234−14xx
=1x2x−1xxx+13xx+1234
我们可以先用树状数组计算出
li=∑ij=1[aj<ai],ri=∑nj=i[aj<ai]
计算
1xxx
,我们可以枚举
1
的位置
1xxx=∑i=1n(n−i−ri3)
计算 1234 ,我们可以枚举 3 的位置
1234=∑i=1n(n−i−ri)∗∑j=1i([aj<ai]∗lj)
计算 1x2x ,我们可以枚举 2 的位置
我们可以通过计算满足 (ax<ai,x<i,y<i) 的减去其中 (ay<ai,x<y<i) 的和 (y≤x<i) 的,即
1x2x=∑i=1n(n−i−ri)∗(li∗(i−1)−li∗(li−1)2−∑j=1i([aj<ai]∗j))
计算 13xx ,我么可以枚举 3 的位置
13xx=∑i=1n(n−i−ri)∗(∑j=in([aj<ai]∗(aj−1))−ri∗(ri−1)2)
所有形如 ∑j 都可以使用树状数组维护。
代码:
#include<iostream>
#include<cstdio>
#include<cstring>
#define ll long long
#define up(x,y) x=((ll)(x)+(y))&mod
using namespace std;
const int maxn=200010;
const int mod=16777215;
int n,a[maxn],l[maxn],r[maxn],c[maxn],c1xxx,c1234,c1x2x,c13xx;
void add(int x,int d){for(;x<=n;x+=(x&-x)) c[x]=(c[x]+d)&mod;}
int qry(int x){int r=0;for(;x;x-=(x&-x)) r=(r+c[x])&mod; return r;}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
scanf("%d",&a[i]);
for(int i=1;i<=n;i++)
{
l[i]=qry(a[i]);r[i]=a[i]-l[i]-1;
ll tmp=n-i-r[i];if(tmp>2) up(c1xxx,tmp*(tmp-1)*(tmp-2)/6);
add(a[i],1);
}
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++) up(c1234,(n-i-r[i])*qry(a[i])),add(a[i],l[i]);
memset(c,0,sizeof(c));
for(int i=1;i<=n;i++) up(c1x2x,(ll)(n-i-r[i])*(l[i]*(i-1)-l[i]*(l[i]-1)/2-qry(a[i]))),add(a[i],i);
memset(c,0,sizeof(c));
for(int i=n;i;i--) up(c13xx,(ll)(n-i-r[i])*(qry(a[i])-r[i]*(r[i]-1)/2)),add(a[i],a[i]-1);
printf("%d",(mod+1-c1xxx+c1234+c1x2x+c13xx)&mod);
return 0;
}