[题目概述]
给定三个整数数组
A=[A1,A2,…AN],A=[A_1,A_2,…A_N],A=[A1,A2,…AN],
B=[B1,B2,…BN],B=[B_1,B_2,…B_N],B=[B1,B2,…BN],
C=[C1,C2,…CN],C=[C_1,C_2,…C_N],C=[C1,C2,…CN],
请你统计有多少个三元组 (i,j,k)
满足:
1≤i,j,k≤N1 ≤ i, j, k ≤ N1≤i,j,k≤N
Ai<Bj<CkA_i < B_j < C_kAi<Bj<Ck
输入格式
第一行包含一个整数 N。
第二行包含 N 个整数 A1,A2,…ANA_1,A_2,…A_NA1,A2,…AN
第三行包含 N 个整数 B1,B2,…BNB_1,B_2,…B_NB1,B2,…BN
第四行包含 N 个整数 C1,C2,…CNC_1,C_2,…C_NC1,C2,…CN
输出格式
一个整数表示答案。
数据范围
1 ≤ N ≤ 10510^5105,
0≤ Ai,Bi,CiA_i,B_i,C_iAi,Bi,Ci ≤ 10510^5105
输入样例:
3
1 1 1
2 2 2
3 3 3
输出样例:
27
- 分析题目
题目就是让我们从三组数中选出三个数,满足A中的数小于B中的数小于C中的数。那么我们最先想到的就是三重循环分别枚举三个数,但很显然会超时,因为1 ≤ N ≤ 10510^5105,所以我们最多只能枚举一个数,如果我们枚举A中的数,那么B C 是有联系的,我们无法往下计算,但如果我们枚举B中的数,A C 是相互独立的,那么我们只要从A中选出小于当前枚举的B中的数,从C中选出大于当前枚举的B的数就可,分析到这里就可以想到用二分法来解了。代码相对不是那么难写。 - 细节问题
- 二分法枚举后,符合条件的数有多少呢?
A中的数量应该是 l + 1 个而不是 l 个,因为我们的下标从0开始。
C中的数量应该是 n - l 个而不是 n - 1 - l 个。 - 边界问题处理
if (a[l] >= b[j]) l = -1; if (c[p] <= b[j]) p = n; - 二分法枚举后,符合条件的数有多少呢?
- 完整代码
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
using namespace std;
const int N = 100005;
int a[N], b[N], c[N];
int n, sum;
int main () {
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];
for (int j = 0; j < n; j ++) {
sort(a, a + n);
sort(c, c + n);
int l = 0, r = n - 1;
while (l < r) {
int mid = (l + r + 1) / 2;
if (a[mid] < b[j])
l = mid;
else
r = mid - 1;
}
if (a[l] >= b[j])
l = -1;
int p = 0, q = n - 1;
while (p < q) {
int mid = (p + q) / 2;
if (c[mid] > b[j])
q = mid;
else
p = mid + 1;
}
if (c[p] <= b[j])
p = n;
sum += (l + 1) * (n - p); // A C 是相互独立的,数量应该乘起来
}
cout << sum << endl;
return 0;
}
- 本题就分享完毕了,有问题的小伙伴可以在评论区留言
记得点赞关注加收藏!
文章介绍了使用二分查找优化求解给定整数数组A、B、C中满足A_i<B_j<C_k条件的三元组个数的方法。
1218

被折叠的 条评论
为什么被折叠?



