[bzoj1145]图腾
阅读原文时间:2023年07月08日阅读:3

如果将关系用一个数字来表示(相等表示不确定),那么题目相当于要计算
$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
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 }

手机扫一扫

移动阅读更方便

阿里云服务器
腾讯云服务器
七牛云服务器

你可能感兴趣的文章