1 条题解

  • 0
    @ 2022-2-20 21:32:58

    一个比较常规的思路,考虑每对 i,ji,j 对答案的贡献。

    先考虑 pp 的方案数。

    显然,设 aa 排序后的序列为 bb,然后考虑总方案就是,idiid_i 表示 aia_i 的排名:

    tot=i=1n(bii+1)tot=\prod_{i=1}^n (b_i-i+1)

    然后考虑一对 i,j,i<ji,j,i<j

    如果 ai<aja_i<a_j

    由于 pi>pjp_i>p_j,所以 aj>aia_j>a_i 的部分可以无视。

    那么对应的方案数就是

    $$\frac{tot(a_i-id_i)}{2(a_j-id_j+1)}\times \prod_{k=i+1}^{j-1} \frac {b_k-id_k}{b_k-id_k+1} $$

    解释一下这个式子,左边的部分是因为 pi>pjp_i>p_jpj>pip_j>p_i 是对称的,可以总方案除以二。

    如果 pjaip_j\le a_i 那么会导致中间那些数的选择方案书减少一。

    如果 ai>aja_i>a_j

    由于实际上就是与上面的情况相反,那么方案数就是:

    $$tot-\frac{tot(a_i-id_i)}{2(a_j-id_j+1)}\times \prod_{k=i+1}^{j-1} \frac {b_k-id_k}{b_k-id_k+1} $$

    然后考虑维护上面这个东西。

    从小到大做,插入到线段树里,右边部分就是全局乘,左边的直接维护就好了。


    代码
    #include<bits/stdc++.h>
    #define mid (l+r>>1)
    #define lid p<<1,l,mid
    #define rid p<<1|1,mid+1,r
    #define seg int p,int l,int r
    using namespace std;
    const int mod=1e9+7,N=2e5+5;
    struct hzy{int id,x;}a[N];
    struct segtree{int sum1,sum2,la;}tr[N<<2];
    int kuai(int a,int b){
        int ans=1;
        for(;b;b>>=1,a=1ll*a*a%mod)if(b&1)ans=1ll*ans*a%mod;
        return ans;
    }
    void pd(seg){
        tr[p<<1].sum1=1ll*tr[p<<1].sum1*tr[p].la%mod;
        tr[p<<1|1].sum1=1ll*tr[p<<1|1].sum1*tr[p].la%mod;
        tr[p<<1].la=1ll*tr[p<<1].la*tr[p].la%mod;
        tr[p<<1|1].la=1ll*tr[p<<1|1].la*tr[p].la%mod;
        tr[p].la=1;
    }
    int ask1(seg,int L,int R){
        if(l>=L&&r<=R)return tr[p].sum1;
        if(tr[p].la!=1)pd(p,l,r);
        return ((L<=mid?ask1(lid,L,R):0)+(R>mid?ask1(rid,L,R):0))%mod;
    }
    int ask2(seg,int L,int R){
        if(l>=L&&r<=R)return tr[p].sum2;
        if(tr[p].la!=1)pd(p,l,r);
        return ((L<=mid?ask2(lid,L,R):0)+(R>mid?ask2(rid,L,R):0))%mod;
    }
    void add(seg,int x,int z){
        if(l==r){tr[p].sum1=z,tr[p].sum2=1;return;}
        if(tr[p].la!=1)pd(p,l,r);
        if(x<=mid)add(lid,x,z);
        else add(rid,x,z);
        tr[p].sum1=(tr[p<<1].sum1+tr[p<<1|1].sum1)%mod;
        tr[p].sum2=tr[p<<1].sum2+tr[p<<1|1].sum2;
    }
    int n,tot=1,ans;
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++)scanf("%d",&a[i].x),a[i].id=i;
        for(int i=1;i<=4*n;i++)tr[i].la=1;
        sort(a+1,a+n+1,[](hzy a,hzy b){return a.x<b.x;});
        for(int i=1;i<=n;i++)tot=1ll*tot*(a[i].x-i+1)%mod;
        if(!tot)return puts("0"),0;
        int Inv2=kuai(2,mod-2);
        for(int i=1;i<=n;i++){
            int l=ask1(1,1,n,1,a[i].id),r=ask1(1,1,n,a[i].id,n),R=ask2(1,1,n,a[i].id,n),Inv=kuai(a[i].x-i+1,mod-2);
            ans=(((ans+1ll*l*Inv%mod)%mod+1ll*R*tot%mod)%mod-1ll*r*Inv%mod+mod)%mod;
            tr[1].la=1ll*tr[1].la*(a[i].x-i)%mod*Inv%mod;
            add(1,1,n,a[i].id,1ll*tot*Inv2%mod*(a[i].x-i)%mod);
        }
        printf("%d",ans);
    }
    
    • 1

    信息

    ID
    75
    时间
    1000ms
    内存
    256MiB
    难度
    (无)
    标签
    递交数
    0
    已通过
    0
    上传者