题解:CF251A Points on Line

题面

Points on Line

题面翻译

题目描述

Petya 很喜欢点。最近,他的妈妈给了他 \(n\) 个位于\(OX\)(实数轴)上的点。现在 Petya 想知道有多少种不同的方法可以在数轴上选择 \(3\) 个不同点,使 \(3\) 个点中距离最远的两个点的距离不超过\(d\)

注意: \(3\) 个点的排列顺序是无关紧要的(意思就是说, \(3\) 个点是相同的,交换顺序也只算 \(1\) 种)。

输入输出格式

输入格式:

第一行有两个数:\(n\left ( 1 \le n \le 10^5 \right )\)\(d\left ( 1 \le d \le 10^9 \right )\)。下面一行包含n个整数 \(x_1,x_2,x_3,x_4, \dots x_n\)(绝对值小于等于\(10^9\)),表示妈妈给 Petya 的点的坐标。

保证坐标按绝对升序输入。

输出格式:

输出一个整数————选出三个数,使最远的两个数之间的距离不超过d,的方法数。

在C++中,请不要用 %lld 来读入64位的整数。推荐使用 cincout%l64d 来读入。

说明

在样例一中,任何挑选方式都是可行的。

在样例二中只有 \({-3, -2, -1}\)\({-2, -1, 0}\) 是可行的。

在第三个样例中只有 \({1, 10, 20}\) 是可行的。

题目描述

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.

输入格式

The first line contains two integers: \(n\) and \(d\) ( \(1<=n<=10^{5}, 1<=d<=10^{9}\) ). The next line contains \(n\) integers \(x_{1},x_{2},...,x_{n}\) , their absolute value doesn't exceed \(10^{9}\) — the \(x\) -coordinates of the points that Petya has got.

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

输出格式

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.

样例 #1

样例输入 #1

4 3
1 2 3 4

样例输出 #1

4

样例 #2

样例输入 #2

4 2
-3 -2 -1 0

样例输出 #2

2

样例 #3

样例输入 #3

5 19
1 10 20 30 50

样例输出 #3

1

提示

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}\).

题解

思路

1.暴力 \(O\left ( n^{3} \right )\)

暴力枚举 \(3\) 个数,符合要求就将答案加 \(1\)

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,d,a[100005],ans=0;
signed main(){
	cin.tie(0),cout.tie(0);
	cin>>n>>d;
	for(int i=1;i<=n;i++)	cin>>a[i];
	for(int i=1;i<=n;i++)
		for(int j=i+1;j<=n;j++)
			for(int k=j+1;k<=n;k++)
				if(a[k]-a[i]<=d)
					ans++;
	
	cout<<ans<<"\n";
	return 0;
}

恭喜!TLE

2.正解 \(O \left ( n\log_{}{n} \right )\)

  • 枚举最小的数。
  • 二分找出最大的合法的数。
  • 排列组合求出答案。

设最小的数的位置为 \(l\),最大的数的位置为 \(r\)。所以 r = (upper_bound( a + l, a + 1 + n, a[l] + d) - a - 1),因此当前的的合法选择有 \(C_{r-l}^{2}\) 种方案。

#include<bits/stdc++.h>
#define int long long
using namespace std;
int n,d,a[100005],ans=0;
int C(int x){//组合数
	return (x*(x-1))/2;
}
signed main(){
	cin.tie(0),cout.tie(0);
	cin>>n>>d;
	for(int i=1;i<=n;i++)	cin>>a[i];
	for(int i=1;i<=n;i++){
		int r=(upper_bound(a+i,a+1+n,a[i]+d)-a-1);
		ans+=C(r-i);
	}
	cout<<ans<<"\n";
	return 0;
}

AC 记录

posted @ 2024-08-28 22:54  ggc114514  阅读(18)  评论(0)    收藏  举报