[bzoj1145]图腾
如果将关系用一个数字来表示(相等表示不确定),那么题目相当于要计算
$1324-1243-1432$
=$(1323-1423)-(1233-1234)-(1322-1423)$
=$1323+1234-(1322+1233)$
=$1323+1234-1222-(1324+1342)$
先预处理出li表示i左边比i小的数,ri表示i右边比i大的数(线段树即可),然后对于一下每一项分别考虑如何统计:
1.1323,枚举1的位置i,右边有ri种,左边容斥,答案为任意-312-112=$li*(i-1)-li*(li-1)/2-\sum_{j=1}^{i-1}[aj<ai]*j$
2.1234,枚举3的位置i,右边有ri种,左边有$\sum_{j=1}^{i-1}[aj<ai]*lj$种
3.1222,枚举1的位置i,右边有$C_{ri}^{3}$种
4.1324+1342,枚举3的位置i,将整个拆分成4和12,4有ri种,再对1和3的位置关系容斥,即任意-312-321=$\sum_{j=i+1}^{n}[aj<ai]*(aj-1)-c(n-i-ri,2)$
1 #include<bits/stdc++.h> 2 using namespace std; 3 #define N 200005 4 #define mod 16777216 5 #define L (k<<1) 6 #define R (L+1) 7 #define mid (l+r>>1) 8 int n,ans,a[N],l[N],r[N],f[N<<2]; 9 int c2(int k){ 10 return 1LL*k*(k-1)/2%mod; 11 } 12 int c3(int k){ 13 return 1LL*k*(k-1)*(k-2)/6%mod; 14 } 15 void update(int k,int l,int r,int x,int y){ 16 if (l==r){ 17 f[k]=(f[k]+y)%mod; 18 return; 19 } 20 if (x<=mid)update(L,l,mid,x,y); 21 else update(R,mid+1,r,x,y); 22 f[k]=(f[L]+f[R])%mod; 23 } 24 int query(int k,int l,int r,int x,int y){ 25 if ((l>y)||(x>r))return 0; 26 if ((x<=l)&&(r<=y))return f[k]; 27 return (query(L,l,mid,x,y)+query(R,mid+1,r,x,y))%mod; 28 } 29 int main(){ 30 scanf("%d",&n); 31 for(int i=1;i<=n;i++)scanf("%d",&a[i]); 32 for(int i=1;i<=n;i++){ 33 update(1,1,n,a[i],1); 34 l[i]=query(1,1,n,1,a[i]-1); 35 r[i]=n-i-(a[i]-l[i]-1); 36 ans=((ans+1LL*r[i]*(l[i]*(i-1LL)-c2(l[i]))-c3(r[i]))%mod+mod)%mod; 37 } 38 memset(f,0,sizeof(f)); 39 for(int i=1;i<=n;i++){ 40 update(1,1,n,a[i],l[i]-i); 41 ans=(ans+1LL*r[i]*query(1,1,n,1,a[i]-1))%mod; 42 } 43 memset(f,0,sizeof(f)); 44 for(int i=n;i;i--){ 45 update(1,1,n,a[i],a[i]-1); 46 ans=(ans+1LL*r[i]*(query(1,1,n,1,a[i]-1)-c2(n-i-r[i])+mod))%mod; 47 } 48 printf("%d",ans); 49 }