题面
Points on Line
题面翻译
题目描述
Petya 很喜欢点。最近,他的妈妈给了他 n n n 个位于 O X OX OX(实数轴)上的点。现在 Petya 想知道有多少种不同的方法可以在数轴上选择 3 3 3 个不同点,使 3 3 3 个点中距离最远的两个点的距离不超过 d d d。
注意: 3 3 3 个点的排列顺序是无关紧要的(意思就是说, 3 3 3 个点是相同的,交换顺序也只算 1 1 1 种)。
输入输出格式
输入格式:
第一行有两个数: n ( 1 ≤ n ≤ 1 0 5 ) n\left ( 1 \le n \le 10^5 \right ) n(1≤n≤105), d ( 1 ≤ d ≤ 1 0 9 ) d\left ( 1 \le d \le 10^9 \right ) d(1≤d≤109)。下面一行包含n个整数 x 1 , x 2 , x 3 , x 4 , … x n x_1,x_2,x_3,x_4, \dots x_n x1,x2,x3,x4,…xn(绝对值小于等于 1 0 9 10^9 109),表示妈妈给 Petya 的点的坐标。
保证坐标按绝对升序输入。
输出格式:
输出一个整数————选出三个数,使最远的两个数之间的距离不超过d,的方法数。
在C++中,请不要用 %lld
来读入64位的整数。推荐使用 cin
和 cout
或 %l64d
来读入。
说明
在样例一中,任何挑选方式都是可行的。
在样例二中只有 − 3 , − 2 , − 1 {-3, -2, -1} −3,−2,−1 和 − 2 , − 1 , 0 {-2, -1, 0} −2,−1,0 是可行的。
在第三个样例中只有 1 , 10 , 20 {1, 10, 20} 1,10,20 是可行的。
题目描述
Little Petya likes points a lot. Recently his mom has presented him n n n points lying on the line O X OX 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 d 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 n n and d d d ( 1 < = n < = 1 0 5 , 1 < = d < = 1 0 9 1<=n<=10^{5}, 1<=d<=10^{9} 1<=n<=105,1<=d<=109 ). The next line contains n n n integers x 1 , x 2 , . . . , x n x_{1},x_{2},...,x_{n} x1,x2,...,xn , their absolute value doesn’t exceed 1 0 9 10^{9} 109 — the x x 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 d 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 {-3, -2, -1} −3,−2,−1 and − 2 , − 1 , 0 {-2, -1, 0} −2,−1,0.
In the third sample only one group does: 1 , 10 , 20 {1, 10, 20} 1,10,20.
题解
思路
1.暴力 O ( n 3 ) O\left ( n^{3} \right ) O(n3)
暴力枚举 3 3 3 个数,符合要求就将答案加 1 1 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 ( n log n ) O \left ( n\log_{}{n} \right ) O(nlogn)
- 枚举最小的数。
- 二分找出最大的合法的数。
- 排列组合求出答案。
设最小的数的位置为
l
l
l,最大的数的位置为
r
r
r。所以 r = (upper_bound( a + l, a + 1 + n, a[l] + d) - a - 1)
,因此当前的的合法选择有
C
r
−
l
2
C_{r-l}^{2}
Cr−l2 种方案。
#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;
}