【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 }