LA 4329 Ping pong

#include <iostream>
#include <cstring>
#include <cstdio>
using namespace std;
const int Max=20010;
const int inf=100000;
int lm[Max],rm[Max],a[Max],c[Max*10];
int n;
long long lowbit(long long x)
{
    return x&-x;
}
int sum(long long x,int *c)
{
    int ret=0;
    while(x>0)
    {
        ret+=c[x];
        x-=lowbit(x);
    }
    return ret;
}
void add(long long x,int d,int *c)
{
    while(x<=inf)      
    {
        c[x]+=d;
        x+=lowbit(x);
    }
}
int main()
{
    int T;
    for(scanf("%d",&T);T;T--)
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i]);
        }
        memset(c,0,sizeof(c));
        add(a[1],1,c);
        for(int i=2;i<=n;i++)
        {
            lm[i]=sum(a[i],c);
            add(a[i],1,c);
        }
        memset(c,0,sizeof(c));
        add(a[n],1,c);
        for(int i=n-1;i>=1;i--)
        {
            rm[i]=sum(a[i],c);
            add(a[i],1,c);
        }
        long long ans=0;
        for(int i=1;i<=n;i++)
        {
  //          cout<<i<<" lm: "<<lm[i]<<" rm: "<<rm[i]<<endl;
            ans+=lm[i]*(n-i-rm[i])+(i-1-lm[i])*rm[i];
        }
        printf("%lld\n",ans);
    }
    return 0;
}

 

题意:n个人,每个人都有一个能力值,每次举办比赛都要三个人,举办条件:

如果 i,j,k进行比赛时,如果k是裁判,必须要i<j<k(下标)而且ai<aj<ak(能力值)

思路:只要枚举每个人当裁判是他左边小于他的数个数lm和他右边小于他的数的个数rm

那么答案就是(左边总人数-lm)*(rm)+(lm)*(右边总人数-rm)

如果对每个lm和rm进行枚举的话那么时间会是n^2

可以对树状数组的add操作加以改变,将从ci数组定以为此时ai出现之前的小于ai的数的个数

动态加一,然后求1到ai的sum值

 

posted @ 2016-04-07 19:27  江南何采莲  阅读(220)  评论(0编辑  收藏  举报