题目连接:CodeForces 251A Points on Line
题目大意:具体讲什么真心没看懂,不过最下面有对测试数据的解释,所以就大概懂了,就是给出n和k,然后给出一个大小为n的集合,问从集合中取出3个数,最大数与最小数的差值小于k的方式有多少种。
解题思路:很明显的二分啊,对于num[i], 假设num[i]必取,有多少种情况,令c = num[i] + k, 找到j,使得num[j] > c && num[j - 1] <= c, 这样(i, j)就为可选区间,注意是选取两个,记得用组合数的公式。
#include <iostream>
#include <stdio.h>
#include <algorithm>
using namespace std;
const int N = 100005;
int n, dis, d[N];
long long sum;
long long count (long long ans) {
if (ans < 2) return 0;
return ans * (ans - 1) / 2;
}
int search(int c) {
int l = -1, r = n;
while (l < r) {
int mid = (l + r) / 2;
if (d[mid] < c) l = mid;
else if (d[mid] > c) r = mid;
else return mid + 1;
if (l == r - 1) return r;
}
}
void solve() {
sum = 0;
for (int i = 0; i < n; i ++)
sum += count(search(d[i] + dis) - i - 1);
}
int main () {
scanf("%d%d", &n, &dis);
for (int i = 0; i < n; i++)
scanf("%d", &d[i]);
sort(d, d + n);
solve();
cout << sum << endl ;
return 0;
}