```cpp
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<math.h>
using namespace std;
int a[200500];
int qceil(double a) {
int s = (int)a;
if (a - s > 1e-6) {
s++;
}
return s;
}
int main()
{
long long n, c,k,cnt=0;//不开long long见祖宗
scanf("%d%d", &n, &c);
for (int i = 0; i < n; i++) {
scanf("%d", &a[i]);
}
int left = 0, right = n - 1;
sort(a, a + n);
for (int i = n - 1; i >= 0; i--) {//按照你原来的写法,遇上20w个1又如何应对呢
k = a[i] - c;
left = 0, right = i;
while (left < right) {
if (k <= a[(left + right) / 2])
right = (left + right) / 2;
else
if (right - left != 1) {
left = (left + right) / 2;
}
else {
left = qceil((left * 1.0 + right) / 2);
}
}//以上while循环未改动
right=i;//接下来是重头戏,此时left已经定位好了,把right反回去,重新二分查找
int t=left;//记录left的位置,后面有大用
while (left < right) {
if (k < a[(left + right) / 2])//这里去掉了等于号,意思为,当遇到相同的数时,left向右移
right = (left + right) / 2;
else
if (right - left != 1) {
left = (left + right) / 2;
}
else {
left = qceil((left * 1.0 + right) / 2);
}
}//好了,right也定位了
if(k==a[t])
cnt+=right-t;//right-t的意思是k的个数
}
printf("%lld", cnt);//不开long long见祖宗,#3不tle也得wa
return 0;
}
/*既然用c++了,不考虑用强大的STL吗?
upper_bound(),意为返回所寻找的数在数组中最后出现的位置
lower_bound(),返回所寻找的数在数组中第一次出现的位置
所以
right-t=upper_bound(a,a+n,k)-lower_bound(a,a+n,k)*/
by Silvestorm @ 2023-11-02 12:00:18
@[Silvestorm](/user/1098851) OrzOrzOrz
by Kotori_Kawaii @ 2023-11-02 14:41:43
@[Silvestorm](/user/1098851) 哥你这思路太清晰了 我根本没想到再次二分 确实二分完之后我的操作又是暴力枚举了 太通透了QAQ
by Kotori_Kawaii @ 2023-11-02 14:50:46
@[Silvestorm](/user/1098851) 健宁也跟我说了让我了解一下这方面 正在努力实现ing qwq
by Kotori_Kawaii @ 2023-11-02 14:53:29
@[Kotori_Kawaii](/user/1053560) 某些题用c++确实方便,我是支持你学c++的
by Silvestorm @ 2023-11-02 15:08:56
@[Silvestorm](/user/1098851) (*^▽^*)
by Kotori_Kawaii @ 2023-11-02 15:12:32