uva1428树状数组

用树状数组统计每个点i,左边与右边与多少个点小于a[i],然后用乘法原理和加法原理得出答案

#pragma GCC optimize(2)
#include <bits/stdc++.h>
#define ll long long
#define ls(i)   i<<1
#define rs(i)   i<<1|1
using namespace std;
const int N = 1e5+10;
ll bit[N],lx[N],rx[N],a[N];
int lowbit(int x)
{
    return x&(-x);
}
void add(int x,int val)
{
    while(x<N)
    {
        bit[x]+=val;
        x+=lowbit(x);
    }
}
ll query(int x)
{
    ll ans=0;
    while(x>0)
    {
        ans+=bit[x];
        x-=lowbit(x);
    }
    return ans;
}
int main(){
    int T;
    cin>>T;
    while(T--)
    {
        int n;
        cin>>n;
        for(int i=1;i<=n;i++)
        {
            cin>>a[i];
        }
        memset(bit,0,sizeof(bit));
        for(int i=1;i<=n;i++)
        {
            lx[i]=query(a[i]);
            add(a[i],1);
        }
        memset(bit,0,sizeof(bit));
        for(int i=n;i>=1;i--)
        {
            rx[i]=query(a[i]);
            add(a[i],1);
        }
        ll ans=0;
        for(int i=1;i<=n;i++)
        {
            ans+=lx[i]*(n-i-rx[i])+(i-lx[i]-1)*rx[i];
        }
        cout<<ans<<"\n";
    }
    return 0;
}

 

posted @ 2019-10-14 16:54  hh13579  阅读(100)  评论(0编辑  收藏  举报