#include<iostream>
#include<cmath>
#include<cstring>
#include<algorithm>
#include<vector>
#define ll long long
using namespace std;
int main() {
ll n, m; cin >> n >> m;
vector<int>mp;
for (ll i = 0; i < n; i++) {
ll x; cin >> x; mp.emplace_back(x);
}
sort(mp.begin(), mp.end());
ll left, right;
ll sum = 0;
for (ll i = 0; i < n; i++) {
ll l = i + 1,r = n - 1;
if (l > r)break;//最后一次l>r 会多计算一次 退出
ll Min = abs(m - mp[i]), Max = m + mp[i];
while (l <= r) {//找Min 添两个等号 为了找离Min最近并且大于Min的数
ll mid = (l + r) / 2;
if (mp[mid] <= Min) {
l = mid + 1;
}
else r = mid - 1;
}
r = n - 1; left = l;
while (l <= r) {//找Max
ll mid = (l + r) / 2;
if (mp[mid] >= Max) {
r = mid - 1;
}
else l = mid + 1;
}
right = r;
sum += right - left + 1;//加1能补回来
}
cout << sum;
return 0;
}
1.两层for循环时间的优化
哈希表查找时间为O(1)
二分法优化时间2.边界条件 找离Min最近并且比Min大 所以循环条件两个=
找离Max最近并且比Max小 所以循环条件两个=3.暴力会超时
4.思考
二分查找是找一个数,通过升序序列 每次找中间的来规划范围
找Min a[mid]<=Min l=mid+1 else r=mid-1;
找离Min最近并且比Min大的数
while(l<=r) a[mid]<=mid l=mid+1 (等于Min的时候l就会+1)