题目详细:
![](https://img-blog.csdnimg.cn/img_convert/1e85f549bcfce488d5d22fc6c922b98f.png)
解题思路:
排序加二分:
因为对于数列的顺序没有要求
是从数组中任意的选择
所以我们可以把a[]b[]c[]三个数组
先排好序
然后枚举b数组
(为什么枚举b数组了,因为如果枚举a或者c数组的话,它所约束的数组只有b一个,对于另外一个数组我们还需要取遍历一遍。但如果枚举b数组的话我们就相当于对a和c都有了一个限制,所以只需要枚举b一次即可)
对于枚举出来的方案数
只需要用二分
从排好序的数组中找到符合的范围
用a符合的范围乘以c符合的范围即是正确答案
前缀和:
对于数组中的元素我们可以都映射到
一个数组中去
这个数组例如countA[i]存放的就是
小于i的数的个数
以此对b进行枚举
用a符合的数目个数乘以c符合的数目个数即是正确答案
代码详解:
排序加二分:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=1e5+6;
int a[N],b[N],c[N];
int main(){
int n;
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(b,b+n);
sort(c,c+n);
ll ans=0;
for(int i=0;i<n;i++){
ll aindex=lower_bound(a,a+n,b[i])-a;//找到第一个大于或等b[i]的数
ll cindex=upper_bound(c,c+n,b[i])-c;//找打第一个大于b[i]的数
if(cindex!=n&&aindex>0)//判断是否找到
ans+=aindex*(n-cindex);
}
cout<<ans;
return 0;
}
前缀和:
#include<iostream>
#include<algorithm>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long ll;
const int N=1e5+6;
int a[N],b[N],c[N];
int countA[N],countC[N];
int main(){
int n;
cin>>n;
for(int i=1;i<=n;i++){
scanf(" %d",&a[i]);
countA[a[i]]++;//映射到
}
for(int i=1;i<=n;i++){
scanf(" %d",&b[i]);
}
for(int i=1;i<=n;i++){
scanf(" %d",&c[i]);
countC[c[i]]++;
}
for(int i=1;i<=N-5;i++){
countA[i]+=countA[i-1];//求前缀和
countC[i]+=countC[i-1];
}
ll ans=0;
for(int i=1;i<=n;i++){
ans+=(ll)countA[b[i]-1]*(countC[N-5]-countC[b[i]]);
}
cout<<ans;
return 0;
}