uva1428树状数组

别来无恙 提交于 2019-12-01 08:13:57

用树状数组统计每个点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;
}

 

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!