题目传送门

在数状数组求逆序对的算法,我们可以知道如何在一个序列中计算每一个数后面有多少个数比它小,类似 可以搞到其他属性

#include<iostream>
#include<algorithm>
#include<string.h>
using namespace std;
const int N=2e5+100;
typedef long long ll;
ll a[N],l[N],r[N],b[N],maxx;

ll lowbit(ll x)
{
    return x&(-x);
}
ll n;
ll ask(ll x)
{
    ll res=0;
    for(;x;x-=lowbit(x))
        res+=(ll)b[x];
    return res;
}
void add(ll pos,ll val)
{
    for(;pos<=n;pos+=lowbit(pos))
        b[pos]+=val;

}

void work1()
{
    for(ll i=n;i>0;i--)
    {
        r[i]=ask(maxx)-ask(a[i]);
        add(a[i],1);
    }
    memset(b,0,sizeof b);
    for(ll i=1;i<=n;i++)
    {
        l[i]=ask(maxx)-ask(a[i]);
        add(a[i],1);
    }
    ll ans=0;
    for(int i=1;i<=n;i++) ans=ans+(ll)l[i]*(ll)r[i];
    cout<<ans<<' ';
}
void work2()
{
    memset(b,0,sizeof b);
    for(int i=n;i>0;i--)
    {
        r[i]=ask(a[i]-1);
        add(a[i],1);
    }
    memset(b,0,sizeof b);
    for(int i=1;i<=n;i++)
    {
        l[i]=ask(a[i]-1);
        add(a[i],1);
    }
    ll ans=0;
    for(int i=1;i<=n;i++) ans+=l[i]*r[i];
    cout<<ans<<endl;
}

int main()
{
    ios::sync_with_stdio(false);
    cin>>n;
    for(int i=1;i<=n;i++){
        cin>>a[i];
        maxx=max(maxx,a[i]);
    }
    work1();
    memset(l,0,sizeof l);
    memset(r,0,sizeof r);
    work2();
    return 0;
}

 posted on 2019-08-31 14:53  谁是凶手1703  阅读(46)  评论(0)    收藏  举报