[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 }
View Code

 

posted @ 2020-02-23 11:55  PYWBKTDA  阅读(174)  评论(0编辑  收藏  举报