题目描述
给定三个整数数组
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。
输出格式
一个整数表示答案。
数据范围
1 ≤ N ≤ 10^5,
0 ≤ Ai,Bi,Ci ≤ 10^5
输入样例
3
1 1 1
2 2 2
3 3 3
输出样例
27
算法1
STL中的二分函数
C++ 代码
#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long lld;
const int N = 100005;
int a[N], b[N], c[N];
int n;
lld sum;
int main()
{
scanf("%d", &n);
for (int i = 1; i <= n; i++)
scanf("%d", &a[i]);
for (int i = 1; i <= n; i++)
scanf("%d", &b[i]);
for (int i = 1; i <= n; i++)
scanf("%d", &c[i]);
//由于二分的前提是单调序列 所以预先对a b c排序 直接sort
sort(a + 1, a + 1 + n);
sort(b + 1, b + 1 + n);
sort(c + 1, c + 1 + n);
for (int i = 1; i <= n; i++)
{
//直接用STL中的两个二分函数解决
lld x = (lower_bound(a + 1, a + 1 + n, b[i]) - a) - 1; //在数组a中找比b[i]小的数
lld y = n - (upper_bound(c + 1, c + 1 + n, b[i]) - c) + 1; //在数组c中找比b[i]大的数
sum += x * y;
}
printf("%lld", sum);
return 0;
}
1.stl在二分找不到的时候,返回a.end(),
2.对地址的加减得到的相当于是两个地址的距离
3.注意数组是从1开始的
请问大佬x和y为什么要那样写呢,我还是有点看不懂
建议去看一下STL的库,lower_bound(x)返回的是该元素的迭代器
tql
tql
orz
请问大佬lld x = (lower_bound(a + 1, a + 1 + n, b[i]) - a) - 1; 为什么最后要减去1啊?
因为lower_bound()是返回大于等于b[i]的值,要求小于所以-1
因为(lower_bound(a + 1, a + 1 + n, b[i]) - a)返回的是下标 因为已经排过序了的 lower_bound 返回的是第一个大于或者等于b[i]的值 然后-a的话 那么返回的就是下标 找到了第一个的话 那么下标减去一也就是前面的那些都是比当前的这个小了
写的真好
思路清晰,代码一流
我去太秀了
强!
(upper_bound(c + 1, c + 1 + n, b[i]) - c) 这一句话是不是就是需要找到了在数组c的下标啊,如果不减去c的话,就是变成了位置也就是地址了对吗
是这样的
lower_bound 不是找到第一个 不小于 b[i]的数吗,如果存在相同怎么a[i] 和 b[i]相同,不就不对吗
因为-1了,所以往前一个,又因为下标从1开始,所以正好,不管是等于还是大于。
能说的更清楚些吗
如果存在和b[i]相等的数,那么减去一之后肯定是小于x的索引,不可能减去一之后还会和a[i]相等,因为如果-1相等的话,返回的肯定是等于b[i]的索引
这也太强了吧,就是不想自己写二分,这下有这两个函数,学到了~
学到了!这个方法更加简单!
是的hh 比手写二分简单一丢丢
学到了,lower_bound函数,试了用0作为数组起始下标代码会很简洁
对滴!
0作为起始,最后sum是多少阿,我写的一直输出不对
把那个加一减一去掉