HDU_2492_Ping pong

摘抄自白书:考虑第i个人当裁判的情形。假设a[1]到a[i-1]有c[i]个比a[i]小,那么就(i-1)-c[i]个比a[i]大;同理,假设a[i+1]到a[n]中有d[i]个比a[i]小,那么就有(n-i)-d[i]个比a[i]大。根据乘法原理和加法原理,i当裁判有c[i]*(n-i-d[i])+(i-c[i]-1)*d[i]种比赛。这样,问题就转发为c[i]和d[i]。

#include<iostream>

#include<cstdio>

#include<cstring>

#include<cmath>

#include<algorithm>

#include<string>

#include<queue>

using namespace std;

#define N 100005

#define LL long long

int c[N],a[N],lmin[N],lmax[N],rmin[N],rmax[N];

int sum(int x)

{

    int ret=0;

    while(x)

    {

        ret+=c[x];

        x-=x&-x;

    }

    return ret;

}

void add(int x)

{

    while(x<=N)

    {

        c[x]++;

        x+=x&-x;

    }

}

int main()

{

    int t,i,j,k,n;

    scanf("%d",&t);

    while(t--)

    {

        memset(c,0,sizeof(c));

        scanf("%d",&n);

        for(i=1;i<=n;++i)

        scanf("%d",&a[i]);

        for(i=1;i<=n;++i)

        {

            add(a[i]);

            lmin[i]=sum(a[i]-1);

            lmax[i]=i-1-lmin[i];

        }

        memset(c,0,sizeof(c));

        for(i=n,j=1;i>0;--i,++j)

        {

            add(a[i]);

            rmin[i]=sum(a[i]-1);

            rmax[i]=j-1-rmin[i];

        }

        LL ans=0;

        for(i=1;i<=n;++i)

        {

            ans+=lmin[i]*rmax[i]+rmin[i]*lmax[i];

        }

        printf("%I64d\n",ans);

    }

    return 0;

}

 

你可能感兴趣的:(ping)