hdu 4000 Fruit Ninja

/*



题目:

    给出序列,其中一个子序列为(x,y,z),问最多有多少个这样的子序列,

    使得x<z<y,其中该序列为1到n的排列



分析:

    由于是排列,所以不存在相同的元素,所以x,y,z互不相等。所以序列中

    的大小关系可表示为

    小中大+小大中 = 小__ __ ,所以答案 小大中 = 小__ __ -小中大

    统计 小__ __可以统计该位后面的所有元素中比他大的个数为x,则

        小__ __  = x*(x-1)/2

    而统计小中大时,只需要统计前面比他小的以及后面比他大的个数x,y,则

        小中大 = x*y

    统计个数可以用树状数组来统计,树状数组可以统计出前面已加入的元素比

    当前的元素小的个数



*/

#include <iostream>

#include <cstdio>

#include <cstring>



using namespace std;



#define MOD 100000007

#define X 100005



int a[X];

long long c[X],big[X],sma[X];



int lowbit(int x)

{

    return x & -x;

}



void modify(int x)

{

    while(x<X)

    {

        c[x] = (c[x]+1)%MOD;

        x += lowbit(x);

    }

}



long long query(int x)

{

    long long ret = 0;

    while(x>0)

    {

        ret += c[x];

        ret %= MOD;

        x -= lowbit(x);

    }

    return ret;

}





int main()

{

    freopen("sum.in","r",stdin);

    freopen("sum.out","w",stdout);

    int cnt = 0,t,n;

    cin>>t;

    while(t--)

    {

        printf("Case #%d: ",++cnt);

        scanf("%d",&n);

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

        memset(big,0,sizeof(big));

        memset(sma,0,sizeof(sma));

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

        {

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

            sma[i] = query(a[i]);   ///统计前面比他小的个数

            modify(a[i]);

        }



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

        for(int i=n;i>=1;i--)       ///统计后面比他大的个数

        {

            big[i] = n-i-query(a[i]);

            modify(a[i]);

        }

        long long s = 0,b = 0;

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

        {

            s = (s+(big[i]-1)*big[i]/2)%MOD;    ///统计小__ __的个数

            b = (b+big[i]*sma[i])%MOD;          ///统计小中大的个数

        }

        cout<<(s-b+MOD)%MOD<<endl;

    }

    return 0;

}

 

你可能感兴趣的:(HDU)