CodeForces - 252C:Points on Line(暴力,优化)

本文探讨了一个有趣的算法问题,即在给定的严格递增数列中,寻找所有可能的三元组,这些三元组的最大元素与最小元素之差不超过预设值k。通过详细的思路解析和优化后的AC代码示例,读者可以深入理解如何高效地解决此类问题。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Discription
Little Petya likes points a lot. Recently his mom has presented him n points lying on the line OX. Now Petya is wondering in how many ways he can choose three distinct points so that the distance between the two farthest of them doesn’t exceed d.

Note that the order of the points inside the group of three chosen points doesn’t matter.

Input
The first line contains two integers: n and d (1 ≤ n ≤ 105; 1 ≤ d ≤ 109). The next line contains n integers x1, x2, …, xn, their absolute value doesn’t exceed 109 — the x-coordinates of the points that Petya has got.

It is guaranteed that the coordinates of the points in the input strictly increase.

Output
Print a single integer — the number of groups of three points, where the distance between two farthest points doesn’t exceed d.

Please do not use the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cin, cout streams or the %I64d specifier.

Examples
Input

4 3
1 2 3 4

Output

4

Input

4 2
-3 -2 -1 0

Output

2

Input

5 19
1 10 20 30 50

Output

1

Note
In the first sample any group of three points meets our conditions.

In the seconds sample only 2 groups of three points meet our conditions: {-3, -2, -1} and {-2, -1, 0}.

In the third sample only one group does: {1, 10, 20}.

题意
输入一个n,一个k,和一个长度为n的严格递增的数列
从数列中选取3个数组成一个数列,要求最大的数和最小的数差值最大不能超过k,求出这样的数列的数量。

思路
从头暴力循环第一个数的位置,第二重循环找到第一个不符合条件的位置,两者最差-1就是后两位数的成立区间,利用排列组合,从中选取两个。求解个数。
优化,对于第二重循环,暴力过一遍的数不会再暴力了,大大降低了复杂度。

AC代码

#include<bits/stdc++.h>
using namespace std;
int n,k;
long long ans;
int a[100010],x;
int main()
{
    cin>>n>>k;
    memset(a,0x3f,sizeof(a));
    for(int i=1;i<=n;i++)
    {
        cin>>x;
        a[i]=x;
    }
    long long j=1;
    for(long long i=1;i<=n-2;i++)
    {
        while(a[j]-a[i]<=k&&j<=n)
            j++;
        if(j-i>=3)
            ans+=(j-i-1)*(j-i-2)/2;
    }
    cout<<ans<<endl;
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值