http://acm.hdu.edu.cn/showproblem.php?pid=5792
思路:用树状数组统计每个数前面比他小的数lmin,大的数lmax,后面比他小的数rmin,大的数rmax,不考虑条件总的数量是lmin,lmax的和,去掉不满足的:a=c rmax[]*rmin[] ,a=d lmax[]*rmax[] , b=c lmin[]*rmin[] ,b=d lmin[]*lmax[]就是答案
#include <iostream>
#include <cstdio>
#include <cstring>
#include <vector>
#include <map>
#include <algorithm>
using namespace std;
typedef long long ll;
const int maxn=50005;
int a[maxn],c[maxn];
int lmin[maxn],lmax[maxn],rmin[maxn],rmax[maxn];
vector<int>V;
map<int,int>M;
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int add)
{
while(x<maxn)
{
c[x]+=add;
x+=lowbit(x);
}
}
int sum(int x)
{
int ret=0;
while(x)
{
ret+=c[x];
x-=lowbit(x);
}
return ret;
}
int main()
{
int n;
while(~scanf("%d",&n))
{
memset(c,0,sizeof(c));
V.clear();
M.clear();
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i]);
V.push_back(a[i]);
}
sort(V.begin(),V.end());
V.erase(unique(V.begin(),V.end()),V.end());//去重
for(int i=0;i<V.size();i++)//离散化
M[V[i]]=i+1;
for(int i=1;i<=n;i++)
a[i]=M[a[i]];
ll ans=0,ans1=0,ans2=0;
for(int i=1;i<=n;i++)
{
update(a[i],1);
lmin[i]=sum(a[i]-1);当前位置左边比他小的有多少个
lmax[i]=sum(maxn-1)-sum(a[i]);已经出现的数肯定是他左边的数,在这个时候记录数轴上有多少个数再减去小于等于的,就是大于的了
}
memset(c,0,sizeof(c));
for(int i=n;i>=1;i--)
{
update(a[i],1);
rmin[i]=sum(a[i]-1);
rmax[i]=sum(maxn-1)-sum(a[i]);
}
for(int i=1;i<=n;i++)
{
ans1+=lmin[i];//升序的对数
ans2+=lmax[i];//逆序的对数
}
ans=ans1*ans2;
for(int i=1;i<=n;i++)
ans-=(rmax[i]*rmin[i]+lmax[i]*rmax[i]+lmin[i]*rmin[i]+lmin[i]*lmax[i]);
cout<<ans<<endl;
}
return 0;
}