两个函数介绍:lower_bound 和 upper_bound 假设有一个序列5 5 5 6 6 6
lower_bound(5) 求的是第一个5 若只是 6 6 6 那么求的是第一个6
upper_bound(5) 求的是第一个6
思路:每次求a里面比b[i]小的个数和c里面比b[i]大的个数。
算法一:二分位置求个数
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 100010;
int a[N],b[N],c[N];
int n;
LL res;
int main()
{
cin>>n;
for(int i=0;i<n;++i)scanf("%d",&a[i]);
for(int i=0;i<n;++i)scanf("%d",&b[i]);
for(int i=0;i<n;++i)scanf("%d",&c[i]);
sort(a,a+n);sort(c,c+n);
for(int i=0;i<n;++i)
{
LL t1 = lower_bound(a,a+n,b[i])-a;
LL t2 = n-(upper_bound(c,c+n,b[i])-c);
res+=(t1*t2);
}
cout<<res<<endl;
return 0;
}
算法二:预处理前缀和(先把数组0~i的数字个数预处理一下)
#include<iostream>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 100010;
int a[N],b[N],c[N];
int cnt[N],s[N];
int ab[N],bc[N];
int n;
LL res;
int main()
{
cin>>n;
for(int i=0;i<n;++i)scanf("%d",&a[i]);
for(int i=0;i<n;++i)scanf("%d",&b[i]);
for(int i=0;i<n;++i)scanf("%d",&c[i]);
for(int i=0;i<n;++i)cnt[a[i]]++;
s[0]=cnt[0];
for(int i=1;i<N;++i)s[i]=s[i-1]+cnt[i];
for(int i=0;i<n;++i)ab[i]=s[b[i]-1];
memset(cnt,0,sizeof cnt);
memset(s,0,sizeof s);
for(int i=0;i<n;++i)cnt[c[i]]++;
s[0]=cnt[0];
for(int i=1;i<N;++i)s[i]=s[i-1]+cnt[i];
for(int i=0;i<n;++i)bc[i]=s[N-1]-s[b[i]];
for(int i=0;i<n;++i)
{
LL t = 1ll*ab[i]*bc[i];
res+=t;
}
cout<<res<<endl;
return 0;
}