HOJ 2275 Number sequence(树状数组) 大于小于问题

来源:互联网 发布:linux修改网卡配置 编辑:程序博客网 时间:2024/06/14 20:45

题意:给定一个n个元素的数列,令Ai, Aj, Ak,使得 Ai < Aj > Ak 且 i < j < k这样的三个数为一组。求出一共有多少组。


要建立两次树状数组。

首先,我们插入数据进入树状数组时,用一个tmp1数组来记录每个数前面有几个小于它的。这样就保存了 Ai < Aj 的数量了。

之后我们清空数组,再倒着插入一次,用tmp2数据记录每个数前面有几个小于它的。这样保证了Aj > Ak的数量了。

我们一乘即可


  1. #include<cstdio>  
  2. #include<cstring>  
  3. #include<algorithm>  
  4. #include<iostream>  
  5. using namespace std;  
  6. #define M 35000  
  7. #define N 50050  
  8. #define ll long long  
  9. #define lowbit(x) (x&-x)  
  10. int tree[M];  
  11. int num[N];  
  12. ll tmp[N];  
  13. int sum(int rt)  
  14. {  
  15.     int s=0;  
  16.     while(rt>0){  
  17.         s+=tree[rt];  
  18.         rt-=lowbit(rt);  
  19.     }  
  20.     return s;  
  21. }  
  22. void update(int rt)  
  23. {  
  24.     while(rt<=M-1){  
  25.         tree[rt]++;  
  26.         rt+=lowbit(rt);  
  27.     }  
  28. }  
  29. int main()  
  30. {  
  31.     int n;  
  32.     while(~scanf("%d",&n)){  
  33.         memset(tree,0,sizeof(tree));  
  34.         for(int i=1;i<=n;i++){  
  35.             scanf("%d",&num[i]);  
  36.             num[i]++;  
  37.         }  
  38.         ll ans=0;  
  39.         for(int i=1;i<=n;i++){  
  40.             tmp[i]= sum(num[i]-1);  
  41.             update(num[i]);  
  42.         }  
  43.         memset(tree,0,sizeof(tree));  
  44.         for(int i=n;i>=1;i--)  
  45.         {  
  46.             ans+=tmp[i]*(ll)sum(num[i]-1);  
  47.             update(num[i]);  
  48.         }  
  49.         printf("%lld\n",ans);  
  50.     }  
  51.     return 0;  
  52. }