题解: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位的整数。推荐使用 cin 和 cout 或 %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;
}

浙公网安备 33010602011771号