• P4528 [CTSC2008]图腾 题解


    Link

    P4528 [CTSC2008]图腾

    Solve

    一道非常好的思维题。

    直接统计非常难,需要用类似容斥的想法优化一道

    最后的答案

    (=1324-1432-1243)

    (=(1x2x-1423)-(14xx-1423)-(12xx-1234))

    (=1x2x-14xx-12xx+1234)

    (=1x2x-1xxx+13xx+1234)

    (x)表示排名任意,但是不能重复)

    于是我们思考如何算出(1x2x,1xxx,13xx,1234)

    先预处理几个数组(L_i,R_i)

    (L_i=sum_{j<i}[y_j<y_i],R_i=sum_{j>i}[y_j<y_i]),用树状数组维护出来就好了

    接下来看分别怎么求

    1xxx

    比较简单,对于每个(i)后面三个数乱取,就是(sum C_{n-i-R_i}^3)

    1234

    枚举(3)后面的个数就是(n-i-R_i),如果(2)的位置确定了,那么(1)的方案数就是(L_j),所以答案就是(sum_{i} (n-i-R_i)(sum_{j<i,y_j<y_i}L_j))

    用树状数组来维护

    1x2x

    先枚举(2)的位置(i),那右边有(n-i-R_i)中方法,左边我们假设(1)的位置为(j)(2)的位置为(k)

    左边要满足(j<k<i,y_j<y_i,y_k>y_i)

    若只考虑(y_j<y_i,j<i,k<i),方案数是(L_i*(i-1))

    那么就多算了(j<k,y_k<y_ij)(j≥k)的方案

    (j<k,y_k<y_ij)的方案数是(C_{L_i}^2)

    (k≤j),对于每个(j)(k)的取值范围都是([1,j]),所以就是(sum_{p<i,y_p<y_i}p)

    用树状数组维护

    13xx

    枚举(3),那么(4)(n-i-R_i)种选法,(1,2)满足(j<i<k,y_j<y_k<y_i)

    若只考虑(y_j<y_i,y_k<y_i,j<i)那么有(L_i ast(y_i-1))种选法,需要减去(k≤i)(y_j>y_k)的方案数

    (k≤i)(C_{L_i}^2)

    (y_kleq y_j),对于每个(j),(k)的取值都可以取到所有(y<y_j)的位置,每个(k)的取值范围为([1,p[j]])所以就是(sum_{p<i,y_p<y_i}y_p)

    用树状数组维护

    此题非常灵活的运用了树状数组,是个好题,好好看好好学,

    Code

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxn=200005;
    const LL TT=16777216;
    LL p[maxn],L[maxn],R[maxn],c[maxn],ans,N;
    inline int read(){
    	int ret=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-f;ch=getchar();}
    	while(ch<='9'&&ch>='0')ret=ret*10+ch-'0',ch=getchar();
    	return ret*f;
    }
    void add_x(int x,LL data){
    	for(int i=x;i<=N;i+=i&-i)c[i]=(c[i]+data)%TT;
    	return ;
    }
    int get(int x){
    	LL S=0;
    	for(int i=x;i;i-=i&-i)S=(S+c[i])%TT;
    	return S;
    }
    int main(){
    	freopen("P4528.in","r",stdin);
    	freopen("P4528.out","w",stdout);
    	N=read();
    	for(int i=1;i<=N;i++)p[i]=read();
    	for(int i=1;i<=N;i++)L[i]=get(p[i]),R[i]=p[i]-L[i]-1,add_x(p[i],1);
    	for(int i=1;i<=N;i++){
    		LL x=N-i-R[i];
    		ans=(ans-(x*(x-1)*(x-2)/6)%TT+TT)%TT;//1xxx
    	}
    	memset(c,0,sizeof c);
    	for(int i=1;i<=N;i++){
    		ans=(ans+(N-i-R[i])*get(p[i])%TT)%TT;//1234
    		add_x(p[i],L[i]);
    	}
    	memset(c,0,sizeof c);
    	for(int i=1;i<=N;i++){
    		ans=(ans+(L[i]*(i-1)-get(p[i])-(L[i]-1)*L[i]/2)*(N-i-R[i])%TT+TT)%TT;//1x2x
    		add_x(p[i],i);
    	}
    	memset(c,0,sizeof c);
    	for(int i=1;i<=N;i++){
    		ans=(ans+(L[i]*(p[i]-1)-(L[i]-1)*L[i]/2-get(p[i]))*(N-i-R[i])%TT+TT)%TT;//13xx
    		add_x(p[i],p[i]);
    	}
    	printf("%lld
    ",ans);
    	return 0;
    }
    
  • 相关阅读:
    面向使用的软件设计随笔13
    面向使用的软件设计随笔12
    面向使用的软件设计随笔11
    面向使用的软件设计随笔10
    面向使用的软件设计随笔09
    面向使用的软件设计随笔08
    面向使用的软件设计随笔07
    Tensorflow入门----占位符、常量和Session
    关于卷积
    tensorflow学习笔记
  • 原文地址:https://www.cnblogs.com/martian148/p/13878318.html
Copyright © 2020-2023  润新知