樹狀數組專題(十)之hdu4000

//題目大意:給一串數字,找出所有滿足a[x]<a[z]<a[y]
//其中x,y,z滿足x<y<z;
//採用用全部可能的減去不可能的就是答案的思想
//a[i] 後面有t個比a[i]大.則t*(t-1)/2就是可能的
//再減去形成x<y<z的情況就是答案
//這裏重點講解處理連續遞增的情形..
//有點dp記錄的思想..
//比如現在處理的位置有一個5.那麼需要考慮的就是前面已經出現了的
//比5小的數的組合有多少種..全部加起來就是以5爲末端的組合的個數.
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#include<string.h>
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int MN = 100100;
const __int64 m = 100000007;
int tree[MN+3];
int Lowbit(int x)
{
    return x&(-x);
}
int Getsum(int x)
{
    int sum = 0;
    while(x > 0)
    {
        sum += tree[x];
        x -= Lowbit(x);
    }
    return sum;
}
void Updata(int x)
{
    for(int i = x ;i <= MN ; i += Lowbit(i))
    {
          tree[i]++;
    }
}
int main()
{
    int test;
    while(scanf("%d",&test) != EOF)
    {
        int cas = 0;
        while(test--)
        {
            int n;
            cas++;
            __int64  ans = 0;
            scanf("%d",&n);
            memset(tree,0,sizeof(tree));
            for(int i = 1 ; i <= n ; i++)
            {
                int a;
                scanf("%d",&a);
                Updata(a);
                __int64 tem1 = Getsum(a-1);
                __int64 tem2 = n - a -( i - tem1 - 1);
                ans += tem2 * (tem2-1)/2;//這裏注意.因爲*出來是先儲存在tem
                ans -= (tem1*tem2);//裏面在加給ans,所以如果不是__int64就會超,出錯


            }
            printf("Case #%d: %I64d\n",cas,ans%m);
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章