【HDU 4000】 树状数组

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4000

题目大意:给出n个数,求(x<z<y)的次数 。(x,y,z一次先后出现)

 

解题思路:

题目数据量很大,暴力肯定不行的。

设现在出现的位置为x,后面比它大的数有s个。s个选两个(y,z)有s*(s-1)/2种。此时yz无序。

然后按题目要求x<z<y,所以还要把x<y<z除掉。

 

 1 #include <iostream>

 2 #include <cstdio>

 3 #include <algorithm>

 4 #include <cstring>

 5 using namespace std;

 6 

 7 const int maxn=100005;

 8 const int mod=100000007;

 9 int bit[maxn];

10 int  n;

11 

12 int lowbit(int x)

13 {

14     return x&(-x);

15 }

16 

17 void add(int x, int val)

18 {

19     while(x<=n)

20     {

21         bit[x]+=val;

22         x+=lowbit(x);

23     }

24 }

25 

26 int sum(int x)

27 {

28     int cnt=0;

29     while(x>0)

30     {

31         cnt+=bit[x];

32         x-=lowbit(x);

33     }

34     return cnt;

35 }

36 

37 int main()

38 {

39     int  T, tcase=0, tmp1, tmp2, a;

40     cin >> T;

41     while(T--)

42     {

43         cin >> n;

44         __int64 ans=0;

45         memset(bit,0,sizeof(bit));

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

47         {

48             scanf("%d",&a);

49             add(a,1);

50             tmp1=sum(a-1);     //a前面比a小的数的个数

51             tmp2=n-a-(i-tmp1-1);  //a后面比a大的数的个数

52             ans-=tmp1*tmp2;    //减去x<y<z这种情况

53             if(tmp2>=2)

54                ans+=tmp2*(tmp2-1)/2;  

55         }

56         printf("Case #%d: %d\n",++tcase,ans%mod);

57     }

58     return 0;

59 }

 

 

你可能感兴趣的:(树状数组)