AcWing 1945. 奶牛棒球
题目描述
农夫约翰的 N 头奶牛排成一排,每头奶牛都位于数轴中的不同位置上。
它们正在练习投掷棒球。
农夫约翰观看时,观察到一组三头牛 (X,Y,Z) 完成了两次成功的投掷。
牛 X 把球扔给她右边的牛 Y,然后牛 Y 把球扔给她右边的牛 Z。
约翰指出,第二次投掷的距离不少于第一次投掷的距离,也不超过第一次投掷的距离的两倍。
请计算共有多少组牛 (X,Y,Z) 可能是约翰所看到的。
输入格式
第一行包含整数 N。
接下来 N 行,每行描述一头牛的位置。
输出格式
输出奶牛三元组 (X,Y,Z) 的数量。
(X,Y,Z) 需满足,Y 在 X 的右边,Z 在 Y 的右边,并且从 Y 到 Z 的距离在 [XY,2XY] 之间,其中 XY 表示从 X 到 Y 的距离。
数据范围
3≤N≤1000,
奶牛所在的位置坐标范围 [0,108]。
输入样例:
5
3
1
10
7
4
输出样例:
4
样例解释
四个可能的奶牛三元组为:1−3−7,1−4−7,4−7−10,1−4−10。
解题思路
将奶牛排序后,遍历牛 X、Y 的所有可能,
根据条件 Y 到 Z 的距离在 [XY,2XY] 之间查找得到牛 Z 的端点,相减得到 Z 的可能数量
安利两个函数(利用二分查找)
lower_bound(begin,end,num)//返回begin到end-1范围内第一个大于或等于num的数字的地址,未找到返回end
upper_bound(begin,end,num)//返回begin到end-1范围内第一个大于num的数字的地址,未找到返回end
//返回的地址减去起始地址begin,得到找到数字在数组中的下标。
代码
#include<iostream>
#include<algorithm>
using namespace std;
int arr[1000];
int main() {
int n;
cin >> n;
int sum = 0;
for (int i = 0; i < n; ++i) {
cin >> arr[i];
}
sort(arr, arr + n);
for (int i = 0; i < n; ++i) {
for (int j = i+1; j < n; ++j) {
int tmp = arr[j] - arr[i];
int a = lower_bound(arr + j + 1, arr + n, arr[j] + tmp) - arr;
if (a != n) {
int b = upper_bound(arr + j + 1, arr + n, arr[j] + tmp * 2) - arr;
sum += (b - a);
}
}
}
cout << sum;
return 0;
}