OCAC暑期比赛第三场 E题 线上的点 题解

Posted ocac

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了OCAC暑期比赛第三场 E题 线上的点 题解相关的知识,希望对你有一定的参考价值。

线上的点
原题链接:http://codeforces.com/problemset/problem/251/A
【题目描述】
一条直线上有 n 个点,他们的坐标分别是 x1,x2,……,xn。没有两个点的坐标相同。
你可以从这些点中挑选出三个点,使得三个点的最大距离不超过 d 。
请求出满足条件的三个点的方案数。
【输入格式】
输入的第一行包含两个整数 n 和 d (1<=n<=10^5; 1<=d<=10^9)。
接下来的一行包含 n 个整数 x1,x2,……,xn,分别表示 n 个点的坐标,坐标的绝对值不超过 10^9。
输入保证坐标是按照递增顺序给你的。
【输出格式】
输出你选择三个点并且这三个点的最大距离不超过 d 的方案总数。
【样例输入1】
4 3
1 2 3 4
【样例输出1】
4
【样例输入2】
4 2
-3 -2 -1 0
【样例输出2】
2
【样例输入3】
5 19
1 10 20 30 50
【样例输出3】
1
【样例解释】
样例1中,任意三个点的组合都满足条件;
样例2中,只有两个组合 -3, -2, -1 和 -2, -1, 0 满足条件;
样例3中,只有一个组合 1, 10, 20 满足条件。
【样例分析】
这道题目涉及的算法:二分。
首先我们遍历 i ,我们设 xi 是我们挑选的组合中的第1个元素,
那么我们可以用二分快速找出 x 中最大的那个满足 xj-xi >= d 的坐标 j ,
那么 xi 到 xj 中,除了 xi ,我们需要找出挑选任意两个数的组合,就是 (j-i)*(j-i-1)/2 ,将其加到答案中。
最终循环一遍之后输出答案即可。
实现代码如下:

#include <bits/stdc++.h>
using namespace std;
const int maxn = 100010;

int n;
long long ans, d, a[maxn];

int main() 
    cin >> n >> d;
    for (int i = 0; i < n; i ++) cin >> a[i];
    for (int i = 0; i < n; i ++) 
        int j = upper_bound(a, a+n, a[i]+d) - a - 1;
        long long m = j - i;
        ans += m * (m-1) / 2LL;
    
    cout << ans << endl;
    return 0;

 

以上是关于OCAC暑期比赛第三场 E题 线上的点 题解的主要内容,如果未能解决你的问题,请参考以下文章

OCAC暑期比赛第三场 H题 01字符串 题解

OCAC暑期比赛第三场 F题 魔法力量 题解

OCAC暑期比赛第三场 I题 袋鼠认妈妈 题解

OCAC暑期比赛第三场 J题 袋鼠认妈妈(加强版) 题解

OCAC暑期比赛第一场 E题 有用的数学 题解

OCAC暑期比赛第二场 B题 日常浇花 题解