农夫约翰的 头奶牛排成一排,每头奶牛都位于数轴中的不同位置上。
它们正在练习投掷棒球。
农夫约翰观看时,观察到一组三头牛 完成了两次成功的投掷。
牛 把球扔给她右边的牛
,然后牛
把球扔给她右边的牛
。
约翰指出,第二次投掷的距离不少于第一次投掷的距离,也不超过第一次投掷的距离的两倍。
请计算共有多少组牛 可能是约翰所看到的。
输入格式
第一行包含整数 。
接下来 行,每行描述一头牛的位置。
输出格式
输出奶牛三元组 的数量。
需满足,
在
的右边,
在
的右边,并且从
到
的距离在
之间,其中 XY 表示从
到
的距离。
数据范围
奶牛所在的位置坐标范围 。
输入样例:
5
3
1
10
7
4
输出样例:
4
样例解释
四个可能的奶牛三元组为: 。
解题思路
- 排序(升序排列)
- 枚举
- 然后根据双指针特性(单调性)
二分 找
的范围
- 找第一个满足
的数,找第一个满足
的数
的取值就是
双指针 49ms
using namespace std;
const int N = 1010;
int p[N];
int main(){
int n, res = 0;
cin >> n;
for(int i = 0; i < n; i++) cin >> p[i];
sort(p, p + n);
for(int i = 0; i + 2 < n; i++){
for(int j = i + 1, l = j + 1, r = j + 1; j + 1 < n; j++){
while(l < n && p[l] - p[j] < p[j] - p[i]) l++;
while(r < n && p[r] - p[j] <= 2 * (p[j] - p[i])) r++;
res += (r - l);
}
}
cout << res << endl;
return 0;
}
二分 742ms
using namespace std;
const int N = 1010;
int p[N];
int main(){
int n, res = 0;
cin >> n;
for(int i = 0; i < n; i++) cin >> p[i];
sort(p, p + n);
for(int i = 0; i + 2 < n; i++){
for(int j = i + 1; j + 1 < n; j++){
int l = lower_bound(p, p + n, 2 * p[j] - p[i]) - p;
int r = upper_bound(p, p + n, 3 * p[j] - 2 * p[i]) - p;
res += (r - l);
}
}
cout << res << endl;
return 0;
}