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;
}

 

posted @ 2013-05-27 21:47  小仪在努力~  阅读(141)  评论(0编辑  收藏  举报