题目
给定三个整数数组
A = [A1, A2, … AN],
B = [B1, B2, … BN],
C = [C1, C2, … CN],
请你统计有多少个三元组(i, j, k) 满足:
- 1 <= i, j, k <= N
- Ai < Bj < Ck
输入
第一行包含一个整数N。 第二行包含N个整数A1, A2, … AN。 第三行包含N个整数B1, B2, … BN。 第四行包含N个整数C1, C2, … CN。
输出
一个整数表示答案
样例输入
3
1 1 1
2 2 2
3 3 3
样例输出
27
思路
暴力求解很容易,写三层for循环加上判断就能求出来了,但是时间复杂度太大,所以需要换一种思路。
很明显我们需要先把三个数组排序一下。然后三元组要求满足Ai < Bj < Ck,所以我们可以对于每一个Bj,找出A中A[j]之前最大的小于Bj的元素Ai,然后再在C中找到第一个大于Bj的元素Ck,那么很明显,Ai之前的元素都小于Bj,Ck之后的元素都大于Ck,所以当B取Bj时有i*(N-k)多个三元组。然后按照这种方法遍历完B数组就可以找到结果了。因为i,k下标不会往前移,只会往后移,所以复杂度是O(n)的。
代码
#include <iostream>
#include <algorithm>
const int MAXN = 1e5 + 10;
int A[MAXN];
int B[MAXN];
int C[MAXN];
using namespace std;
int main()
{
int N;
scanf("%d",&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);
long long res = 0;
//暴力求解
// for(int i =0;i<N;i++){
// for(int j = 0;j<N;j++){
// if(A[i]>=B[j]){
// continue;
// }
// for(int k = 0;k<N;k++){
// if(B[j]>=C[k]){
// continue;
// }
// res++;
// }
// }
//
// }
int i=0,j=0,k=0;
while(j<N){
while(i<N&&A[i]<B[j])
i++;
while(k<N&&C[k]<=B[j])
k++;
res += i*(N-k);
j++;
}
printf("%d\n",res);
return 0;
}