首页 > 代码库 > HDU 2492 Ping pong

HDU 2492 Ping pong

题意:

一串数字  问  有几种这样的组合(x,y,z)使得x>y>z或x<y<z  y在x数字后面z在y后面  题目中每种数字是唯一的


思路:

对于一个数字  比如 f  它计算出的ans值为 

( beforef.lessthanf * afterf.biggerthanf )+( beforef.biggerthanf * afterf.lessthanf )

易知 beforef.biggerthanf = locationf - 1 - beforef.lessthanf 同理after

则式子可化简为 

( beforef.lessthanf * ( n - locationf - afterf.lessthanf ) )+( (locationf - 1 - beforef.lessthanf ) * afterf.lessthanf )

如果我们从小到大的处理每个数字  那么可知当前处理的数字是当前序列中最大的

则 afterf.lessthanf = nowallnumber - beforef.lessthanf

那么式子中将只出现一个未知数  也就是说我们只需要知道当前位置前有几个小于自己即可

因此用树状数组维护


代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define N 20010
#define lowbit(x) (x&(-x))

int t,n;
int a[N];
__int64 ans;
struct person
{
    int id,val;
    bool operator<(const person fa) const
    {
        return val<fa.val;
    }
}f[N];

void add(int x)
{
    while(x<=n)
    {
        a[x]+=1;
        x+=lowbit(x);
    }
}

int sum(int x)
{
    int res=0;
    while(x)
    {
        res+=a[x];
        x-=lowbit(x);
    }
    return res;
}

int main()
{
    int i,ls,lb,rs,rb,id;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        for(i=1;i<=n;i++)
        {
            f[i].id=i;
            scanf("%d",&f[i].val);
        }
        sort(f+1,f+1+n);
        memset(a,0,sizeof(a));
        ans=0;
        for(i=1;i<=n;i++)
        {
            id=f[i].id;
            ls=sum(id);
            lb=id-ls-1;
            rs=sum(n)-ls;
            rb=n-id-rs;
            ans+=ls*rb;
            ans+=lb*rs;
            add(id);
        }
        printf("%I64d\n",ans);
    }
    return 0;
}