思路:对于V,我们只需要枚举每个点左边比它大的个数为m,右边比它大的个数为n,那么就有m*n个
我们用数组res[i]为1表示某个数是否出现,S[i]来表示res[i]的前缀和,那么我们要找前面比5大的个数,不就是S[N]-S[5]嘛
我们只需要动态维护两个数组,很明显运用树状数组就可以解决这个问题
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=2e5+5;
ll a[N],t[N];
ll low[N],high[N];
int n;
ll lowbit(ll x)
{
return x&-x;
}
void add(ll x,ll k)
{
for(ll i=x;i<=n;i+=lowbit(i)) t[i]+=k;
}
ll ask(ll x)
{
ll res=0;
for(ll i=x;i;i-=lowbit(i)) res+=t[i];
return res;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
for(int i=1;i<=n;i++)
{
ll k=a[i];
low[i]=ask(k-1);
high[i]=ask(n)-ask(k);
add(k,1);
}
memset(t,0,sizeof t);
ll t1=0,t2=0;
for(int i=n;i>=1;i--)
{
t1+=high[i]*(ask(n)-ask(a[i]));
t2+=low[i]*(ask(a[i]-1));
add(a[i],1);
}
cout<<t1<<" "<<t2<<endl;
return 0;
}