楼兰图腾——逆序数

题目链接

题意:

在给定的序列中,可以构成多少个‘v’ 和 ‘^’

题解:

‘v‘的解法

由于序列中的数是从小到大给出的,所以我们如果知道a[i]的前面有多少个比他大的数a[i]的后面有多少个比他大的数,那么可以构成的V就是这两个数之积,而最终答案ans就是所有位置积的累加

同理’^‘的解法同理

代码:

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2e5+5;
ll n,m;
ll c[maxn],a[maxn];
ll ldown[maxn],rdown[maxn],lup[maxn],rup[maxn];
void update(ll pos,ll x)
{
    for(ll i=pos;i<=n;i+=i&-i)c[i]+=x;
}
ll query(ll pos)
{
    ll ans=0;
    for(ll i=pos;i;i-=i&-i)ans+=c[i];
    return ans;
}
int main()
{
    scanf("%lld",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%lld",&a[i]);
    }
    for(int i=1;i<=n;i++)
    {
        update(a[i],1);
        ldown[i]=query(a[i]-1);
    }
    memset(c,0,sizeof c);
    for(int i=n;i>0;i--)
    {
        update(a[i],1);
        rdown[i]=query(a[i]-1);
    }
    memset(c,0,sizeof c);
    for(int i=1;i<=n;i++)
    {
        update(a[i],1);
        lup[i]=i-query(a[i]);
       // printf("%d==%d\n",i,lup[i]);
    }
    memset(c,0,sizeof c);
    for(int i=n;i>0;i--)
    {
        update(a[i],1);
        rup[i]=(n-i+1)-query(a[i]);
        //printf("%d==%d\n",i,rup[i]);
    }
    ll ans1=0;
    for(int i=1;i<=n;i++)ans1+=ldown[i]*rdown[i];
    ll ans2=0;
    for(int i=1;i<=n;i++)ans2+=lup[i]*rup[i];
    printf("%lld %lld\n",ans2,ans1);


    return 0;
}
View Code

 

posted @ 2019-10-24 20:56  。小姜  阅读(132)  评论(0编辑  收藏  举报