记得暑假的时候看《亚洲区预选赛真题题解》的时候,看到树状数组那道题,只是勉强看懂思路了!树状数组的结节根本就没有掌握。时隔四个月,再回头看这道题,感觉轻松多了!
对于hdu2492这道题,用树状数组是非常好的选择,代码短,结构简单,不易出错!
其核心的思路在于:假如有a1 a2 a3 a4 a5 a6 a7 a8 a9这段数据,我们枚举每个点,假如到了a4,那么我们需要知道的是:
a1 a2 a3中小于a4的有多少?
a5 a6 a7 8 a9中大于a4的有多少?
这里的统计就用到的树状数组!
把代码贴出来吧!
- #include<stdio.h>
- #include<string.h>
- #define MM 100000
- #define MN 20000
- int n;
- int a[MN+100],tree[2][MM+100];
- int left[MN+100],right[MN+100];
- void init(){
- memset(tree,0,sizeof(tree));
- memset(left,0,sizeof(left));
- memset(right,0,sizeof(right));
- }
- int lowbit(int x){
- return x&(-x);
- }
- void insert(int pos,int flag){
- while(pos<=MM){
- tree[flag][pos]++;
- pos+=lowbit(pos);
- }
- }
- int query(int pos,int flag){
- int ans=0;
- while(pos>0){
- ans+=tree[flag][pos];
- pos-=lowbit(pos);
- }
- return ans;
- }
- int main(){
- int t,i;
- scanf("%d",&t);
- while(t--){
- scanf("%d",&n);
- init();
- for(i=1;i<=n;i++){
- scanf("%d",&a[i]);
- }
- for(i=1;i<=n;i++){
- left[i]=query(a[i]-1,0);
- insert(a[i],0);
- }
- for(i=n;i>0;i--){
- right[i]=query(a[i]-1,1);
- insert(a[i],1);
- }
- long long ans=0;
- for(i=1;i<=n;i++){
- ans+=(long long)left[i]*(long long)(n-i-right[i])+(long long)(i-left[i]-1)*(long long)right[i];
- }
- printf("%I64d\n",ans);
- }
- return 0;
- }