题目描述:
题意
给定三个整数数组
请你统计共有多少个三元数组满足:
输入格式
第一行包含一个整数
第二,三,四行分别输入数组
输出格式
一个整数表示答案。
数据范围
第一种解法:暴力枚举
思路
遍历三个数组,用long long ans来存储三元数组的个数,如果出现满足条件的则ans++
时间复杂度:
代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int N =100010;
int a[N],b[N],c[N];
LL ans;
int n;
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) cin>>b[i];
for(int i=1;i<=n;i++) cin>>c[i];
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
for(int k=1;k<=n;k++){
if(a[i]<b[j]&&b[j]<c[k])
{
ans++;
}
}
}
}
cout<<ans;
return 0;
}
第二种解法:排序+二分
思路
二分 先对三个数组进行sort排序,然后遍历b数组,对于b中的每一个数b[i],在a数组中寻找最后一个。小于b[i]的数的下标,这里我们记做l.在再c数组中寻找第一个大于b[i]的数的下标,这里我们记做r。可知a数组中,小于b[i]的数的个数为l+1,c数组中大于b[i]数的个数为n-r.(下标从0开始)。因此在三元递增组中,以b[i]为中间数的个数为(l+1)*(n-r).。遍历b数组,ans+=(l+1)*(n-r) 即为答案。
时间复杂度
代码
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 100010;
int a[N], b[N], c[N];
int main(){
int n;
cin>>n;
for (int i = 0; i < n; i++) cin>>a[i];
for (int i = 0; i < n; i++) cin>>b[i];
for (int i = 0; i < n; i++) cin>>c[i];
sort(a, a + n);
sort(b, b + n);
sort(c, c + n);
LL ans = 0;
for (int i = 0; i < n; i++){
int l = 0, r = n - 1;
while (l < r){
int mid = (l + r + 1) / 2;
if (a[mid] < b[i]) l = mid;
else r = mid - 1;
}
if (a[l] >= b[i]) l = -1;
int x = l;
l = 0, r = n - 1;
while (l < r){
int mid = (l + r) / 2;
if (c[mid] > b[i]) r = mid;
else l = mid + 1;
}
if (c[l] <= b[i]) r = n;
int y = r;
ans += (LL)(x + 1)*(n - y);
}
cout<<ans;
return 0;
}
————来自acwing的题解
链接:https://www.acwing.com/solution/content/18628/
第三种解法:前缀和+统计
思路
注意到,N的数据范围不大,和A[i]差不多。因此我们可以考虑新建一个数组count,count[i]表示A数组中值为i的数的个数。我们对count数组求前缀和,令其为S[i],则S[i]表示A数组中值为i,i-1,...的数的个数之和,即A数组中小于等于i 的数的个数。因此,对于每一个B[j]而言,S[B[j]-1]表示A中小于B[j]的数的个数。对于C数组而言同理。
我们对count[i]求前缀和时,count原来的值我们已经不需要了,因此完全可以用count数组来存储前缀和的值。
时间复杂度:
代码
#include<iostream>
#include<algorithm>
#include<cstring>
using namespace std;
typedef long long LL;
const int N =10e5+10;
int a[N],b[N],c[N];
int cnt[N];
int as[N],cs[N];
int n;
LL res;
int main(){
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
for(int i=1;i<=n;i++) cin>>b[i];
for(int i=1;i<=n;i++) cin>>c[i];
for(int i=1;i<=n;i++) cnt[a[i]]++;
for(int i=1;i<=N;i++) cnt[i]+=cnt[i-1];
for(int i=1;i<=n;i++) as[i]=cnt[b[i]-1];
memset(cnt,0,sizeof cnt);
for(int i=1;i<=n;i++) cnt[c[i]]++;
for(int i=1;i<=N;i++) cnt[i]+=cnt[i-1];
for(int i=1;i<=n;i++) cs[i]=n-cnt[b[i]];
for(int i=1;i<=n;i++) res+=(LL)as[i]*cs[i];
cout<<res;
}