二分法: 思想其实很早就接触过。
(以下来自360百科)
给定精确度ξ,用二分法求函数f(x)零点近似值的步骤如下:
1 确定区间[a,b],验证f(a)·f(b)<0,给定精确度ξ.
2 求区间(a,b)的中点c.
3 计算f(c).
(1) 若f(c)=0,则c就是函数的零点;
(2) 若f(a)·f(c)<0,则令b=c;
(3) 若f(c)·f(b)<0,则令a=c.
(4) 判断是否达到精确度ξ:即若|a-b|<ξ,则得到零点近似值a(或b),否则重复2-4.
题目描述
给定n个数,从中选出三个数,使得最大的那个减最小的那个的值小于等于d,问有多少种选法。
输入描述:
第一行两个整数n,d(1 <= n <= 100,000,1 <= d <= 1000,000,000); 第二行n个整数满足abs(ai) <= 1,000,000,000。数据保证a单调递增。
输出描述:
输出一个整数表示满足条件的选法。
链接:https://www.nowcoder.com/acm/contest/84/F
来源:牛客网
示例1
输入
4 3 1 2 3 4
输出
4
示例2
输入
4 2 -3 -2 -1 0
输出
2
示例3
输入
5 19 1 10 20 30 50
输出
1
ac:
#include<iostream>
#include<cstdio>
#define ll long long
ll a[100010];
int main()
{
int i,n;
ll d,res,mid,temp;
while (scanf ("%d%lld",&n,&d)!=EOF)
{
res=temp=0;
for (i=1;i<=n;i++)
scanf ("%lld",&a[i]);
for (i=1;i<=n;i++)
{
ll l=i,r=n;temp=0;
while (l<=r)
{
mid =(l+r)>>1;
if (a[mid]-a[i]<=d)
{
temp=mid;
l=mid+1;
}
else
r=mid-1;
}
if (temp!=0&&temp>(i+1))
res=res+(temp-i-1)*(temp-i)/2;
}
printf ("%lld\n",res);
}
return 0;
}