记得暑假的时候看《亚洲区预选赛真题题解》的时候,看到树状数组那道题,只是勉强看懂思路了!树状数组的结节根本就没有掌握。时隔四个月,再回头看这道题,感觉轻松多了!

     对于hdu2492这道题,用树状数组是非常好的选择,代码短,结构简单,不易出错!

     其核心的思路在于:假如有a1 a2 a3 a4 a5 a6 a7 a8 a9这段数据,我们枚举每个点,假如到了a4,那么我们需要知道的是:

          a1 a2 a3中小于a4的有多少?

          a5 a6 a7 8 a9中大于a4的有多少?

     这里的统计就用到的树状数组!

     把代码贴出来吧!

     

   
   
   
   
  1. #include 
  2. #include 
  3. #define MM 100000 
  4. #define MN 20000 
  5. int n; 
  6. int a[MN+100],tree[2][MM+100]; 
  7. int left[MN+100],right[MN+100]; 
  8. void init(){ 
  9.  
  10.     memset(tree,0,sizeof(tree)); 
  11.     memset(left,0,sizeof(left)); 
  12.     memset(right,0,sizeof(right)); 
  13. int lowbit(int x){ 
  14.     return x&(-x); 
  15. void insert(int pos,int flag){ 
  16.     while(pos<=MM){ 
  17.             tree[flag][pos]++; 
  18.         pos+=lowbit(pos); 
  19.     } 
  20. int query(int pos,int flag){ 
  21.     int ans=0; 
  22.     while(pos>0){ 
  23.         ans+=tree[flag][pos]; 
  24.         pos-=lowbit(pos); 
  25.     } 
  26.     return ans; 
  27. int main(){ 
  28.     int t,i; 
  29.     scanf("%d",&t); 
  30.     while(t--){ 
  31.         scanf("%d",&n); 
  32.         init(); 
  33.         for(i=1;i<=n;i++){ 
  34.             scanf("%d",&a[i]); 
  35.         } 
  36.         for(i=1;i<=n;i++){ 
  37.             left[i]=query(a[i]-1,0); 
  38.             insert(a[i],0); 
  39.         } 
  40.         for(i=n;i>0;i--){ 
  41.             right[i]=query(a[i]-1,1); 
  42.             insert(a[i],1); 
  43.         } 
  44.         long long ans=0; 
  45.         for(i=1;i<=n;i++){ 
  46.             ans+=(long long)left[i]*(long long)(n-i-right[i])+(long long)(i-left[i]-1)*(long long)right[i]; 
  47.         } 
  48.         printf("%I64d\n",ans); 
  49.     } 
  50.  
  51.     return 0;